mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 20:22:25 -05:00 
			
		
		
		
	[chore] Validate/set account domain (#619)
* add miekg/dns dependency * set/validate accountDomain
This commit is contained in:
		
					parent
					
						
							
								dfdc473cef
							
						
					
				
			
			
				commit
				
					
						cf5c6d724d
					
				
			
		
					 304 changed files with 34218 additions and 1 deletions
				
			
		|  | @ -224,6 +224,7 @@ The following libraries and frameworks are used by GoToSocial, with gratitude  | |||
| - [jackc/pgx](https://github.com/jackc/pgx); Postgres driver. [MIT License](https://spdx.org/licenses/MIT.html). | ||||
| - [mcuadros/go-syslog](https://github.com/mcuadros/go-syslog); Syslog server library. [MIT License](https://spdx.org/licenses/MIT.html). | ||||
| - [microcosm-cc/bluemonday](https://github.com/microcosm-cc/bluemonday); HTML user-input sanitization. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html). | ||||
| - [miekg/dns](https://github.com/miekg/dns); DNS utilities. [Go License](https://go.dev/LICENSE). | ||||
| - [mitchellh/mapstructure](https://github.com/mitchellh/mapstructure); Go interface => struct parsing. [MIT License](https://spdx.org/licenses/MIT.html). | ||||
| - [modernc.org/sqlite](https://gitlab.com/cznic/sqlite); cgo-free port of SQLite. [Other License](https://gitlab.com/cznic/sqlite/-/blob/master/LICENSE). | ||||
|   - [modernc.org/ccgo](https://gitlab.com/cznic/ccgo); c99 AST -> Go translater. [BSD-3-Clause License](https://spdx.org/licenses/BSD-3-Clause.html). | ||||
|  |  | |||
							
								
								
									
										1
									
								
								go.mod
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
										
									
									
									
								
							|  | @ -94,6 +94,7 @@ require ( | |||
| 	github.com/leodido/go-urn v1.2.1 // indirect | ||||
| 	github.com/magiconair/properties v1.8.6 // indirect | ||||
| 	github.com/mattn/go-isatty v0.0.14 // indirect | ||||
| 	github.com/miekg/dns v1.1.49 // indirect | ||||
| 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | ||||
| 	github.com/modern-go/reflect2 v1.0.2 // indirect | ||||
| 	github.com/pelletier/go-toml v1.9.5 // indirect | ||||
|  |  | |||
							
								
								
									
										10
									
								
								go.sum
									
										
									
									
									
								
							
							
						
						
									
										10
									
								
								go.sum
									
										
									
									
									
								
							|  | @ -391,6 +391,8 @@ github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4 | |||
| github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= | ||||
| github.com/microcosm-cc/bluemonday v1.0.18 h1:6HcxvXDAi3ARt3slx6nTesbvorIc3QeTzBNRvWktHBo= | ||||
| github.com/microcosm-cc/bluemonday v1.0.18/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM= | ||||
| github.com/miekg/dns v1.1.49 h1:qe0mQU3Z/XpFeE+AEBo2rqaS1IPBJ3anmqZ4XiZJVG8= | ||||
| github.com/miekg/dns v1.1.49/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= | ||||
| github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= | ||||
| github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= | ||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | ||||
|  | @ -551,6 +553,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de | |||
| github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
| github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
| github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
| github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= | ||||
| github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= | ||||
| github.com/zeebo/blake3 v0.2.1/go.mod h1:TSQ0KjMH+pht+bRyvVooJ1rBpvvngSGaPISafq9MxJk= | ||||
| github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= | ||||
|  | @ -622,6 +625,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||
| golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= | ||||
| golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= | ||||
| golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||
|  | @ -660,7 +664,9 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY | |||
| golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||
| golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | ||||
| golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= | ||||
| golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= | ||||
| golang.org/x/net v0.0.0-20220524220425-1d687d428aca h1:xTaFYiPROfpPhqrfTIDXj0ri1SpfueYT951s4bAuDO8= | ||||
|  | @ -687,6 +693,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ | |||
| golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
| golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
|  | @ -732,8 +739,10 @@ golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7w | |||
| golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
|  | @ -812,6 +821,7 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f | |||
| golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||||
| golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||||
| golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= | ||||
| golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= | ||||
| golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= | ||||
| golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= | ||||
| golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
|  |  | |||
|  | @ -23,6 +23,7 @@ import ( | |||
| 	"fmt" | ||||
| 	"strings" | ||||
| 
 | ||||
| 	"github.com/miekg/dns" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
| 
 | ||||
|  | @ -31,10 +32,23 @@ func Validate() error { | |||
| 	errs := []error{} | ||||
| 
 | ||||
| 	// host | ||||
| 	if GetHost() == "" { | ||||
| 	host := GetHost() | ||||
| 	if host == "" { | ||||
| 		errs = append(errs, fmt.Errorf("%s must be set", HostFlag())) | ||||
| 	} | ||||
| 
 | ||||
| 	// accountDomain; only check if host was set, otherwise there's no point | ||||
| 	if host != "" { | ||||
| 		switch ad := GetAccountDomain(); ad { | ||||
| 		case "": | ||||
| 			SetAccountDomain(GetHost()) | ||||
| 		default: | ||||
| 			if !dns.IsSubDomain(ad, host) { | ||||
| 				errs = append(errs, fmt.Errorf("%s was %s and %s was %s, but %s is not a valid subdomain of %s", HostFlag(), host, AccountDomainFlag(), ad, host, ad)) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// protocol | ||||
| 	switch proto := GetProtocol(); proto { | ||||
| 	case "https": | ||||
|  |  | |||
|  | @ -46,6 +46,54 @@ func (suite *ConfigValidateTestSuite) TestValidateConfigNoHost() { | |||
| 	suite.EqualError(err, "host must be set") | ||||
| } | ||||
| 
 | ||||
| func (suite *ConfigValidateTestSuite) TestValidateAccountDomainOK1() { | ||||
| 	testrig.InitTestConfig() | ||||
| 
 | ||||
| 	err := config.Validate() | ||||
| 	suite.NoError(err) | ||||
| 
 | ||||
| 	suite.Equal(config.GetHost(), config.GetAccountDomain()) | ||||
| } | ||||
| 
 | ||||
| func (suite *ConfigValidateTestSuite) TestValidateAccountDomainOK2() { | ||||
| 	testrig.InitTestConfig() | ||||
| 
 | ||||
| 	config.SetAccountDomain("localhost:8080") | ||||
| 
 | ||||
| 	err := config.Validate() | ||||
| 	suite.NoError(err) | ||||
| } | ||||
| 
 | ||||
| func (suite *ConfigValidateTestSuite) TestValidateAccountDomainOK3() { | ||||
| 	testrig.InitTestConfig() | ||||
| 
 | ||||
| 	config.SetHost("gts.example.org") | ||||
| 	config.SetAccountDomain("example.org") | ||||
| 
 | ||||
| 	err := config.Validate() | ||||
| 	suite.NoError(err) | ||||
| } | ||||
| 
 | ||||
| func (suite *ConfigValidateTestSuite) TestValidateAccountDomainNotSubdomain1() { | ||||
| 	testrig.InitTestConfig() | ||||
| 
 | ||||
| 	config.SetHost("gts.example.org") | ||||
| 	config.SetAccountDomain("example.com") | ||||
| 
 | ||||
| 	err := config.Validate() | ||||
| 	suite.EqualError(err, "host was gts.example.org and account-domain was example.com, but gts.example.org is not a valid subdomain of example.com") | ||||
| } | ||||
| 
 | ||||
| func (suite *ConfigValidateTestSuite) TestValidateAccountDomainNotSubdomain2() { | ||||
| 	testrig.InitTestConfig() | ||||
| 
 | ||||
| 	config.SetHost("example.org") | ||||
| 	config.SetAccountDomain("gts.example.org") | ||||
| 
 | ||||
| 	err := config.Validate() | ||||
| 	suite.EqualError(err, "host was example.org and account-domain was gts.example.org, but example.org is not a valid subdomain of gts.example.org") | ||||
| } | ||||
| 
 | ||||
| func (suite *ConfigValidateTestSuite) TestValidateConfigNoProtocol() { | ||||
| 	testrig.InitTestConfig() | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										8
									
								
								vendor/github.com/miekg/dns/.codecov.yml
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/miekg/dns/.codecov.yml
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| coverage: | ||||
|   status: | ||||
|     project: | ||||
|       default: | ||||
|         target: 40% | ||||
|         threshold: null | ||||
|     patch: false | ||||
|     changes: false | ||||
							
								
								
									
										4
									
								
								vendor/github.com/miekg/dns/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/miekg/dns/.gitignore
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| *.6 | ||||
| tags | ||||
| test.out | ||||
| a.out | ||||
							
								
								
									
										1
									
								
								vendor/github.com/miekg/dns/AUTHORS
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/miekg/dns/AUTHORS
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| Miek Gieben <miek@miek.nl> | ||||
							
								
								
									
										1
									
								
								vendor/github.com/miekg/dns/CODEOWNERS
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/miekg/dns/CODEOWNERS
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| * @miekg @tmthrgd | ||||
							
								
								
									
										10
									
								
								vendor/github.com/miekg/dns/CONTRIBUTORS
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/miekg/dns/CONTRIBUTORS
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,10 @@ | |||
| Alex A. Skinner | ||||
| Andrew Tunnell-Jones | ||||
| Ask Bjørn Hansen | ||||
| Dave Cheney | ||||
| Dusty Wilson | ||||
| Marek Majkowski | ||||
| Peter van Dijk | ||||
| Omri Bahumi | ||||
| Alex Sergeyev | ||||
| James Hartig | ||||
							
								
								
									
										9
									
								
								vendor/github.com/miekg/dns/COPYRIGHT
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/miekg/dns/COPYRIGHT
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| 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. | ||||
| Extensions of the original work are copyright (c) 2011 Miek Gieben | ||||
| 
 | ||||
| Copyright 2011 Miek Gieben. All rights reserved. Use of this source code is | ||||
| governed by a BSD-style license that can be found in the LICENSE file. | ||||
| 
 | ||||
| Copyright 2014 CloudFlare. All rights reserved. Use of this source code is | ||||
| governed by a BSD-style license that can be found in the LICENSE file. | ||||
							
								
								
									
										30
									
								
								vendor/github.com/miekg/dns/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/miekg/dns/LICENSE
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| 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. | ||||
| 
 | ||||
| As this is fork of the official Go code the same license applies. | ||||
| Extensions of the original work are copyright (c) 2011 Miek Gieben | ||||
							
								
								
									
										33
									
								
								vendor/github.com/miekg/dns/Makefile.fuzz
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/github.com/miekg/dns/Makefile.fuzz
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 | ||||
							
								
								
									
										52
									
								
								vendor/github.com/miekg/dns/Makefile.release
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/miekg/dns/Makefile.release
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 artifacts 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 | ||||
							
								
								
									
										186
									
								
								vendor/github.com/miekg/dns/README.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								vendor/github.com/miekg/dns/README.md
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,186 @@ | |||
| [](https://travis-ci.org/miekg/dns) | ||||
| [](https://codecov.io/github/miekg/dns?branch=master) | ||||
| [](https://goreportcard.com/report/miekg/dns) | ||||
| [](https://godoc.org/github.com/miekg/dns) | ||||
| 
 | ||||
| # Alternative (more granular) approach to a DNS library | ||||
| 
 | ||||
| > Less is more. | ||||
| 
 | ||||
| Complete and usable DNS library. All Resource Records are supported, including the DNSSEC types. | ||||
| It follows a lean and mean philosophy. If there is stuff you should know as a DNS programmer there | ||||
| isn't a convenience function for it. Server side and client side programming is supported, i.e. you | ||||
| can build servers and resolvers with it. | ||||
| 
 | ||||
| We try to keep the "master" branch as sane as possible and at the bleeding edge of standards, | ||||
| avoiding breaking changes wherever reasonable. We support the last two versions of Go. | ||||
| 
 | ||||
| # Goals | ||||
| 
 | ||||
| * KISS; | ||||
| * Fast; | ||||
| * Small API. If it's easy to code in Go, don't make a function for it. | ||||
| 
 | ||||
| # Users | ||||
| 
 | ||||
| A not-so-up-to-date-list-that-may-be-actually-current: | ||||
| 
 | ||||
| * https://github.com/coredns/coredns | ||||
| * https://github.com/abh/geodns | ||||
| * https://github.com/baidu/bfe | ||||
| * http://www.statdns.com/ | ||||
| * http://www.dnsinspect.com/ | ||||
| * https://github.com/chuangbo/jianbing-dictionary-dns | ||||
| * http://www.dns-lg.com/ | ||||
| * https://github.com/fcambus/rrda | ||||
| * https://github.com/kenshinx/godns | ||||
| * https://github.com/skynetservices/skydns | ||||
| * https://github.com/hashicorp/consul | ||||
| * https://github.com/DevelopersPL/godnsagent | ||||
| * https://github.com/duedil-ltd/discodns | ||||
| * https://github.com/StalkR/dns-reverse-proxy | ||||
| * https://github.com/tianon/rawdns | ||||
| * https://mesosphere.github.io/mesos-dns/ | ||||
| * https://github.com/fcambus/statzone | ||||
| * https://github.com/benschw/dns-clb-go | ||||
| * https://github.com/corny/dnscheck for <http://public-dns.info/> | ||||
| * https://github.com/miekg/unbound | ||||
| * https://github.com/miekg/exdns | ||||
| * https://dnslookup.org | ||||
| * https://github.com/looterz/grimd | ||||
| * https://github.com/phamhongviet/serf-dns | ||||
| * https://github.com/mehrdadrad/mylg | ||||
| * https://github.com/bamarni/dockness | ||||
| * https://github.com/fffaraz/microdns | ||||
| * https://github.com/ipdcode/hades <https://jd.com> | ||||
| * https://github.com/StackExchange/dnscontrol/ | ||||
| * https://www.dnsperf.com/ | ||||
| * https://dnssectest.net/ | ||||
| * https://github.com/oif/apex | ||||
| * https://github.com/jedisct1/dnscrypt-proxy | ||||
| * https://github.com/jedisct1/rpdns | ||||
| * https://github.com/xor-gate/sshfp | ||||
| * https://github.com/rs/dnstrace | ||||
| * https://blitiri.com.ar/p/dnss ([github mirror](https://github.com/albertito/dnss)) | ||||
| * https://render.com | ||||
| * https://github.com/peterzen/goresolver | ||||
| * https://github.com/folbricht/routedns | ||||
| * https://domainr.com/ | ||||
| * https://zonedb.org/ | ||||
| * https://router7.org/ | ||||
| * https://github.com/fortio/dnsping | ||||
| * https://github.com/Luzilla/dnsbl_exporter | ||||
| * https://github.com/bodgit/tsig | ||||
| * https://github.com/v2fly/v2ray-core (test only) | ||||
| * https://kuma.io/ | ||||
| * https://www.misaka.io/services/dns | ||||
| * https://ping.sx/dig | ||||
| * https://fleetdeck.io/ | ||||
| * https://github.com/markdingo/autoreverse | ||||
| 
 | ||||
| 
 | ||||
| Send pull request if you want to be listed here. | ||||
| 
 | ||||
| # Features | ||||
| 
 | ||||
| * UDP/TCP queries, IPv4 and IPv6 | ||||
| * RFC 1035 zone file parsing ($INCLUDE, $ORIGIN, $TTL and $GENERATE (for all record types) are supported | ||||
| * Fast | ||||
| * Server side programming (mimicking the net/http package) | ||||
| * Client side programming | ||||
| * DNSSEC: signing, validating and key generation for DSA, RSA, ECDSA and Ed25519 | ||||
| * EDNS0, NSID, Cookies | ||||
| * AXFR/IXFR | ||||
| * TSIG, SIG(0) | ||||
| * DNS over TLS (DoT): encrypted connection between client and server over TCP | ||||
| * DNS name compression | ||||
| 
 | ||||
| Have fun! | ||||
| 
 | ||||
| Miek Gieben  -  2010-2012  -  <miek@miek.nl> | ||||
| DNS Authors 2012- | ||||
| 
 | ||||
| # Building | ||||
| 
 | ||||
| This library uses Go modules and uses semantic versioning. Building is done with the `go` tool, so | ||||
| the following should work: | ||||
| 
 | ||||
|     go get github.com/miekg/dns | ||||
|     go build github.com/miekg/dns | ||||
| 
 | ||||
| ## Examples | ||||
| 
 | ||||
| A short "how to use the API" is at the beginning of doc.go (this also will show when you call `godoc | ||||
| github.com/miekg/dns`). | ||||
| 
 | ||||
| Example programs can be found in the `github.com/miekg/exdns` repository. | ||||
| 
 | ||||
| ## Supported RFCs | ||||
| 
 | ||||
| *all of them* | ||||
| 
 | ||||
| * 103{4,5} - DNS standard | ||||
| * 1348 - NSAP record (removed the record) | ||||
| * 1982 - Serial Arithmetic | ||||
| * 1876 - LOC record | ||||
| * 1995 - IXFR | ||||
| * 1996 - DNS notify | ||||
| * 2136 - DNS Update (dynamic updates) | ||||
| * 2181 - RRset definition - there is no RRset type though, just []RR | ||||
| * 2537 - RSAMD5 DNS keys | ||||
| * 2065 - DNSSEC (updated in later RFCs) | ||||
| * 2671 - EDNS record | ||||
| * 2782 - SRV record | ||||
| * 2845 - TSIG record | ||||
| * 2915 - NAPTR record | ||||
| * 2929 - DNS IANA Considerations | ||||
| * 3110 - RSASHA1 DNS keys | ||||
| * 3123 - APL record | ||||
| * 3225 - DO bit (DNSSEC OK) | ||||
| * 340{1,2,3} - NAPTR record | ||||
| * 3445 - Limiting the scope of (DNS)KEY | ||||
| * 3597 - Unknown RRs | ||||
| * 403{3,4,5} - DNSSEC + validation functions | ||||
| * 4255 - SSHFP record | ||||
| * 4343 - Case insensitivity | ||||
| * 4408 - SPF record | ||||
| * 4509 - SHA256 Hash in DS | ||||
| * 4592 - Wildcards in the DNS | ||||
| * 4635 - HMAC SHA TSIG | ||||
| * 4701 - DHCID | ||||
| * 4892 - id.server | ||||
| * 5001 - NSID | ||||
| * 5155 - NSEC3 record | ||||
| * 5205 - HIP record | ||||
| * 5702 - SHA2 in the DNS | ||||
| * 5936 - AXFR | ||||
| * 5966 - TCP implementation recommendations | ||||
| * 6605 - ECDSA | ||||
| * 6725 - IANA Registry Update | ||||
| * 6742 - ILNP DNS | ||||
| * 6840 - Clarifications and Implementation Notes for DNS Security | ||||
| * 6844 - CAA record | ||||
| * 6891 - EDNS0 update | ||||
| * 6895 - DNS IANA considerations | ||||
| * 6944 - DNSSEC DNSKEY Algorithm Status | ||||
| * 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 | ||||
| * 8080 - EdDSA for DNSSEC | ||||
| * 8499 - DNS Terminology | ||||
| * 8659 - DNS Certification Authority Authorization (CAA) Resource Record | ||||
| * 8914 - Extended DNS Errors | ||||
| * 8976 - Message Digest for DNS Zones (ZONEMD RR) | ||||
| 
 | ||||
| ## Loosely Based Upon | ||||
| 
 | ||||
| * ldns - <https://nlnetlabs.nl/projects/ldns/about/> | ||||
| * NSD - <https://nlnetlabs.nl/projects/nsd/about/> | ||||
| * Net::DNS - <http://www.net-dns.org/> | ||||
| * GRONG - <https://github.com/bortzmeyer/grong> | ||||
							
								
								
									
										62
									
								
								vendor/github.com/miekg/dns/acceptfunc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								vendor/github.com/miekg/dns/acceptfunc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,62 @@ | |||
| package dns | ||||
| 
 | ||||
| // MsgAcceptFunc is used early in the server code to accept or reject a message with RcodeFormatError. | ||||
| // It returns a MsgAcceptAction to indicate what should happen with the message. | ||||
| type MsgAcceptFunc func(dh Header) MsgAcceptAction | ||||
| 
 | ||||
| // DefaultMsgAcceptFunc checks the request and will reject if: | ||||
| // | ||||
| // * isn't a request (don't respond in that case) | ||||
| // | ||||
| // * opcode isn't OpcodeQuery or OpcodeNotify | ||||
| // | ||||
| // * Zero bit isn't zero | ||||
| // | ||||
| // * does not have exactly 1 question in the question section | ||||
| // | ||||
| // * has more than 1 RR in the Answer section | ||||
| // | ||||
| // * has more than 0 RRs in the Authority section | ||||
| // | ||||
| // * has more than 2 RRs in the Additional section | ||||
| // | ||||
| var DefaultMsgAcceptFunc MsgAcceptFunc = defaultMsgAcceptFunc | ||||
| 
 | ||||
| // MsgAcceptAction represents the action to be taken. | ||||
| type MsgAcceptAction int | ||||
| 
 | ||||
| // Allowed returned values from a MsgAcceptFunc. | ||||
| const ( | ||||
| 	MsgAccept               MsgAcceptAction = iota // Accept the message | ||||
| 	MsgReject                                      // Reject the message with a RcodeFormatError | ||||
| 	MsgIgnore                                      // Ignore the error and send nothing back. | ||||
| 	MsgRejectNotImplemented                        // Reject the message with a RcodeNotImplemented | ||||
| ) | ||||
| 
 | ||||
| func defaultMsgAcceptFunc(dh Header) MsgAcceptAction { | ||||
| 	if isResponse := dh.Bits&_QR != 0; isResponse { | ||||
| 		return MsgIgnore | ||||
| 	} | ||||
| 
 | ||||
| 	// Don't allow dynamic updates, because then the sections can contain a whole bunch of RRs. | ||||
| 	opcode := int(dh.Bits>>11) & 0xF | ||||
| 	if opcode != OpcodeQuery && opcode != OpcodeNotify { | ||||
| 		return MsgRejectNotImplemented | ||||
| 	} | ||||
| 
 | ||||
| 	if dh.Qdcount != 1 { | ||||
| 		return MsgReject | ||||
| 	} | ||||
| 	// NOTIFY requests can have a SOA in the ANSWER section. See RFC 1996 Section 3.7 and 3.11. | ||||
| 	if dh.Ancount > 1 { | ||||
| 		return MsgReject | ||||
| 	} | ||||
| 	// IXFR request could have one SOA RR in the NS section. See RFC 1995, section 3. | ||||
| 	if dh.Nscount > 1 { | ||||
| 		return MsgReject | ||||
| 	} | ||||
| 	if dh.Arcount > 2 { | ||||
| 		return MsgReject | ||||
| 	} | ||||
| 	return MsgAccept | ||||
| } | ||||
							
								
								
									
										484
									
								
								vendor/github.com/miekg/dns/client.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										484
									
								
								vendor/github.com/miekg/dns/client.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,484 @@ | |||
| package dns | ||||
| 
 | ||||
| // A client implementation. | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"encoding/binary" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	dnsTimeout     time.Duration = 2 * time.Second | ||||
| 	tcpIdleTimeout time.Duration = 8 * time.Second | ||||
| ) | ||||
| 
 | ||||
| func isPacketConn(c net.Conn) bool { | ||||
| 	if _, ok := c.(net.PacketConn); !ok { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	if ua, ok := c.LocalAddr().(*net.UnixAddr); ok { | ||||
| 		return ua.Net == "unixgram" | ||||
| 	} | ||||
| 
 | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // A Conn represents a connection to a DNS server. | ||||
| 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 in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) | ||||
| 	TsigProvider   TsigProvider      // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations. | ||||
| 	tsigRequestMAC string | ||||
| } | ||||
| 
 | ||||
| func (co *Conn) tsigProvider() TsigProvider { | ||||
| 	if co.TsigProvider != nil { | ||||
| 		return co.TsigProvider | ||||
| 	} | ||||
| 	// tsigSecretProvider will return ErrSecret if co.TsigSecret is nil. | ||||
| 	return tsigSecretProvider(co.TsigSecret) | ||||
| } | ||||
| 
 | ||||
| // A Client defines parameters for a DNS client. | ||||
| type Client struct { | ||||
| 	Net       string      // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP) | ||||
| 	UDPSize   uint16      // minimum receive buffer for UDP messages | ||||
| 	TLSConfig *tls.Config // TLS connection configuration | ||||
| 	Dialer    *net.Dialer // a net.Dialer used to set local address, timeouts and more | ||||
| 	// Timeout is a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout, | ||||
| 	// WriteTimeout when non-zero. Can be overridden with net.Dialer.Timeout (see Client.ExchangeWithDialer and | ||||
| 	// Client.Dialer) or context.Context.Deadline (see ExchangeContext) | ||||
| 	Timeout        time.Duration | ||||
| 	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 in canonical form (lowercase, fqdn, see RFC 4034 Section 6.2) | ||||
| 	TsigProvider   TsigProvider      // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations. | ||||
| 	SingleInflight bool              // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass | ||||
| 	group          singleflight | ||||
| } | ||||
| 
 | ||||
| // Exchange performs a synchronous UDP query. It sends the message m to the address | ||||
| // contained in a and waits for a reply. Exchange does not retry a failed query, nor | ||||
| // will it fall back to TCP in case of truncation. | ||||
| // See client.Exchange for more information on setting larger buffer sizes. | ||||
| func Exchange(m *Msg, a string) (r *Msg, err error) { | ||||
| 	client := Client{Net: "udp"} | ||||
| 	r, _, err = client.Exchange(m, a) | ||||
| 	return r, err | ||||
| } | ||||
| 
 | ||||
| func (c *Client) dialTimeout() time.Duration { | ||||
| 	if c.Timeout != 0 { | ||||
| 		return c.Timeout | ||||
| 	} | ||||
| 	if c.DialTimeout != 0 { | ||||
| 		return c.DialTimeout | ||||
| 	} | ||||
| 	return dnsTimeout | ||||
| } | ||||
| 
 | ||||
| func (c *Client) readTimeout() time.Duration { | ||||
| 	if c.ReadTimeout != 0 { | ||||
| 		return c.ReadTimeout | ||||
| 	} | ||||
| 	return dnsTimeout | ||||
| } | ||||
| 
 | ||||
| func (c *Client) writeTimeout() time.Duration { | ||||
| 	if c.WriteTimeout != 0 { | ||||
| 		return c.WriteTimeout | ||||
| 	} | ||||
| 	return dnsTimeout | ||||
| } | ||||
| 
 | ||||
| // Dial connects to the address on the named network. | ||||
| func (c *Client) Dial(address string) (conn *Conn, err error) { | ||||
| 	return c.DialContext(context.Background(), address) | ||||
| } | ||||
| 
 | ||||
| // DialContext connects to the address on the named network, with a context.Context. | ||||
| // For TLS over TCP (DoT) the context isn't used yet. This will be enabled when Go 1.18 is released. | ||||
| func (c *Client) DialContext(ctx context.Context, address string) (conn *Conn, err error) { | ||||
| 	// create a new dialer with the appropriate timeout | ||||
| 	var d net.Dialer | ||||
| 	if c.Dialer == nil { | ||||
| 		d = net.Dialer{Timeout: c.getTimeoutForRequest(c.dialTimeout())} | ||||
| 	} else { | ||||
| 		d = *c.Dialer | ||||
| 	} | ||||
| 
 | ||||
| 	network := c.Net | ||||
| 	if network == "" { | ||||
| 		network = "udp" | ||||
| 	} | ||||
| 
 | ||||
| 	useTLS := strings.HasPrefix(network, "tcp") && strings.HasSuffix(network, "-tls") | ||||
| 
 | ||||
| 	conn = new(Conn) | ||||
| 	if useTLS { | ||||
| 		network = strings.TrimSuffix(network, "-tls") | ||||
| 
 | ||||
| 		// TODO(miekg): Enable after Go 1.18 is released, to be able to support two prev. releases. | ||||
| 		/* | ||||
| 			tlsDialer := tls.Dialer{ | ||||
| 				NetDialer: &d, | ||||
| 				Config:    c.TLSConfig, | ||||
| 			} | ||||
| 			conn.Conn, err = tlsDialer.DialContext(ctx, network, address) | ||||
| 		*/ | ||||
| 		conn.Conn, err = tls.DialWithDialer(&d, network, address, c.TLSConfig) | ||||
| 	} else { | ||||
| 		conn.Conn, err = d.DialContext(ctx, network, address) | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	conn.UDPSize = c.UDPSize | ||||
| 	return conn, nil | ||||
| } | ||||
| 
 | ||||
| // Exchange performs a synchronous query. It sends the message m to the address | ||||
| // contained in a and waits for a reply. Basic use pattern with a *dns.Client: | ||||
| // | ||||
| //	c := new(dns.Client) | ||||
| //	in, rtt, err := c.Exchange(message, "127.0.0.1:53") | ||||
| // | ||||
| // Exchange does not retry a failed query, nor will it fall back to TCP in | ||||
| // case of truncation. | ||||
| // It is up to the caller to create a message that allows for larger responses to be | ||||
| // returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger | ||||
| // buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit | ||||
| // of 512 bytes | ||||
| // To specify a local address or a timeout, the caller has to set the `Client.Dialer` | ||||
| // attribute appropriately | ||||
| func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error) { | ||||
| 	co, err := c.Dial(address) | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return nil, 0, err | ||||
| 	} | ||||
| 	defer co.Close() | ||||
| 	return c.ExchangeWithConn(m, co) | ||||
| } | ||||
| 
 | ||||
| // ExchangeWithConn has the same behavior as Exchange, just with a predetermined connection | ||||
| // that will be used instead of creating a new one. | ||||
| // Usage pattern with a *dns.Client: | ||||
| // | ||||
| //	c := new(dns.Client) | ||||
| //	// connection management logic goes here | ||||
| // | ||||
| //	conn := c.Dial(address) | ||||
| //	in, rtt, err := c.ExchangeWithConn(message, conn) | ||||
| // | ||||
| // This allows users of the library to implement their own connection management, | ||||
| // as opposed to Exchange, which will always use new connections and incur the added overhead | ||||
| // that entails when using "tcp" and especially "tcp-tls" clients. | ||||
| // | ||||
| // When the singleflight is set for this client the context is _not_ forwarded to the (shared) exchange, to | ||||
| // prevent one cancelation from canceling all outstanding requests. | ||||
| func (c *Client) ExchangeWithConn(m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error) { | ||||
| 	return c.exchangeWithConnContext(context.Background(), m, conn) | ||||
| } | ||||
| 
 | ||||
| func (c *Client) exchangeWithConnContext(ctx context.Context, m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error) { | ||||
| 	if !c.SingleInflight { | ||||
| 		return c.exchangeContext(ctx, m, conn) | ||||
| 	} | ||||
| 
 | ||||
| 	q := m.Question[0] | ||||
| 	key := fmt.Sprintf("%s:%d:%d", q.Name, q.Qtype, q.Qclass) | ||||
| 	r, rtt, err, shared := c.group.Do(key, func() (*Msg, time.Duration, error) { | ||||
| 		// When we're doing singleflight we don't want one context cancelation, cancel _all_ outstanding queries. | ||||
| 		// Hence we ignore the context and use Background(). | ||||
| 		return c.exchangeContext(context.Background(), m, conn) | ||||
| 	}) | ||||
| 	if r != nil && shared { | ||||
| 		r = r.Copy() | ||||
| 	} | ||||
| 
 | ||||
| 	return r, rtt, err | ||||
| } | ||||
| 
 | ||||
| func (c *Client) exchangeContext(ctx context.Context, m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error) { | ||||
| 	opt := m.IsEdns0() | ||||
| 	// If EDNS0 is used use that for size. | ||||
| 	if opt != nil && opt.UDPSize() >= MinMsgSize { | ||||
| 		co.UDPSize = opt.UDPSize() | ||||
| 	} | ||||
| 	// Otherwise use the client's configured UDP size. | ||||
| 	if opt == nil && c.UDPSize >= MinMsgSize { | ||||
| 		co.UDPSize = c.UDPSize | ||||
| 	} | ||||
| 
 | ||||
| 	// write with the appropriate write timeout | ||||
| 	t := time.Now() | ||||
| 	writeDeadline := t.Add(c.getTimeoutForRequest(c.writeTimeout())) | ||||
| 	readDeadline := t.Add(c.getTimeoutForRequest(c.readTimeout())) | ||||
| 	if deadline, ok := ctx.Deadline(); ok { | ||||
| 		if deadline.Before(writeDeadline) { | ||||
| 			writeDeadline = deadline | ||||
| 		} | ||||
| 		if deadline.Before(readDeadline) { | ||||
| 			readDeadline = deadline | ||||
| 		} | ||||
| 	} | ||||
| 	co.SetWriteDeadline(writeDeadline) | ||||
| 	co.SetReadDeadline(readDeadline) | ||||
| 
 | ||||
| 	co.TsigSecret, co.TsigProvider = c.TsigSecret, c.TsigProvider | ||||
| 
 | ||||
| 	if err = co.WriteMsg(m); err != nil { | ||||
| 		return nil, 0, err | ||||
| 	} | ||||
| 
 | ||||
| 	if isPacketConn(co.Conn) { | ||||
| 		for { | ||||
| 			r, err = co.ReadMsg() | ||||
| 			// Ignore replies with mismatched IDs because they might be | ||||
| 			// responses to earlier queries that timed out. | ||||
| 			if err != nil || r.Id == m.Id { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		r, err = co.ReadMsg() | ||||
| 		if err == nil && r.Id != m.Id { | ||||
| 			err = ErrId | ||||
| 		} | ||||
| 	} | ||||
| 	rtt = time.Since(t) | ||||
| 	return r, rtt, err | ||||
| } | ||||
| 
 | ||||
| // ReadMsg reads a message from the connection co. | ||||
| // 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 { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	m := new(Msg) | ||||
| 	if err := m.Unpack(p); err != nil { | ||||
| 		// 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 an erroneous message | ||||
| 		return m, err | ||||
| 	} | ||||
| 	if t := m.IsTsig(); t != nil { | ||||
| 		// Need to work on the original message p, as that was used to calculate the tsig. | ||||
| 		err = tsigVerifyProvider(p, co.tsigProvider(), co.tsigRequestMAC, false) | ||||
| 	} | ||||
| 	return m, err | ||||
| } | ||||
| 
 | ||||
| // ReadMsgHeader reads a DNS message, parses and populates hdr (when hdr is not nil). | ||||
| // Returns message as a byte slice to be parsed with Msg.Unpack later on. | ||||
| // Note that error handling on the message body is not possible as only the header is parsed. | ||||
| func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) { | ||||
| 	var ( | ||||
| 		p   []byte | ||||
| 		n   int | ||||
| 		err error | ||||
| 	) | ||||
| 
 | ||||
| 	if isPacketConn(co.Conn) { | ||||
| 		if co.UDPSize > MinMsgSize { | ||||
| 			p = make([]byte, co.UDPSize) | ||||
| 		} else { | ||||
| 			p = make([]byte, MinMsgSize) | ||||
| 		} | ||||
| 		n, err = co.Read(p) | ||||
| 	} else { | ||||
| 		var length uint16 | ||||
| 		if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		p = make([]byte, length) | ||||
| 		n, err = io.ReadFull(co.Conn, p) | ||||
| 	} | ||||
| 
 | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} else if n < headerSize { | ||||
| 		return nil, ErrShortRead | ||||
| 	} | ||||
| 
 | ||||
| 	p = p[:n] | ||||
| 	if hdr != nil { | ||||
| 		dh, _, err := unpackMsgHdr(p, 0) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		*hdr = dh | ||||
| 	} | ||||
| 	return p, err | ||||
| } | ||||
| 
 | ||||
| // Read implements the net.Conn read method. | ||||
| func (co *Conn) Read(p []byte) (n int, err error) { | ||||
| 	if co.Conn == nil { | ||||
| 		return 0, ErrConnEmpty | ||||
| 	} | ||||
| 
 | ||||
| 	if isPacketConn(co.Conn) { | ||||
| 		// UDP connection | ||||
| 		return co.Conn.Read(p) | ||||
| 	} | ||||
| 
 | ||||
| 	var length uint16 | ||||
| 	if err := binary.Read(co.Conn, binary.BigEndian, &length); err != nil { | ||||
| 		return 0, err | ||||
| 	} | ||||
| 	if int(length) > len(p) { | ||||
| 		return 0, io.ErrShortBuffer | ||||
| 	} | ||||
| 
 | ||||
| 	return io.ReadFull(co.Conn, p[:length]) | ||||
| } | ||||
| 
 | ||||
| // WriteMsg sends a message through the connection co. | ||||
| // If the message m contains a TSIG record the transaction | ||||
| // signature is calculated. | ||||
| func (co *Conn) WriteMsg(m *Msg) (err error) { | ||||
| 	var out []byte | ||||
| 	if t := m.IsTsig(); t != nil { | ||||
| 		// Set tsigRequestMAC for the next read, although only used in zone transfers. | ||||
| 		out, co.tsigRequestMAC, err = tsigGenerateProvider(m, co.tsigProvider(), co.tsigRequestMAC, false) | ||||
| 	} else { | ||||
| 		out, err = m.Pack() | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = co.Write(out) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // Write implements the net.Conn Write method. | ||||
| func (co *Conn) Write(p []byte) (int, error) { | ||||
| 	if len(p) > MaxMsgSize { | ||||
| 		return 0, &Error{err: "message too large"} | ||||
| 	} | ||||
| 
 | ||||
| 	if isPacketConn(co.Conn) { | ||||
| 		return co.Conn.Write(p) | ||||
| 	} | ||||
| 
 | ||||
| 	msg := make([]byte, 2+len(p)) | ||||
| 	binary.BigEndian.PutUint16(msg, uint16(len(p))) | ||||
| 	copy(msg[2:], p) | ||||
| 	return co.Conn.Write(msg) | ||||
| } | ||||
| 
 | ||||
| // Return the appropriate timeout for a specific request | ||||
| func (c *Client) getTimeoutForRequest(timeout time.Duration) time.Duration { | ||||
| 	var requestTimeout time.Duration | ||||
| 	if c.Timeout != 0 { | ||||
| 		requestTimeout = c.Timeout | ||||
| 	} else { | ||||
| 		requestTimeout = timeout | ||||
| 	} | ||||
| 	// net.Dialer.Timeout has priority if smaller than the timeouts computed so | ||||
| 	// far | ||||
| 	if c.Dialer != nil && c.Dialer.Timeout != 0 { | ||||
| 		if c.Dialer.Timeout < requestTimeout { | ||||
| 			requestTimeout = c.Dialer.Timeout | ||||
| 		} | ||||
| 	} | ||||
| 	return requestTimeout | ||||
| } | ||||
| 
 | ||||
| // Dial connects to the address on the named network. | ||||
| func Dial(network, address string) (conn *Conn, err error) { | ||||
| 	conn = new(Conn) | ||||
| 	conn.Conn, err = net.Dial(network, address) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return conn, nil | ||||
| } | ||||
| 
 | ||||
| // ExchangeContext performs a synchronous UDP query, like Exchange. It | ||||
| // additionally obeys deadlines from the passed Context. | ||||
| func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) { | ||||
| 	client := Client{Net: "udp"} | ||||
| 	r, _, err = client.ExchangeContext(ctx, m, a) | ||||
| 	// ignoring rtt to leave the original ExchangeContext API unchanged, but | ||||
| 	// this function will go away | ||||
| 	return r, err | ||||
| } | ||||
| 
 | ||||
| // ExchangeConn performs a synchronous query. It sends the message m via the connection | ||||
| // c and waits for a reply. The connection c is not closed by ExchangeConn. | ||||
| // Deprecated: This function is going away, but can easily be mimicked: | ||||
| // | ||||
| //	co := &dns.Conn{Conn: c} // c is your net.Conn | ||||
| //	co.WriteMsg(m) | ||||
| //	in, _  := co.ReadMsg() | ||||
| //	co.Close() | ||||
| // | ||||
| func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) { | ||||
| 	println("dns: ExchangeConn: this function is deprecated") | ||||
| 	co := new(Conn) | ||||
| 	co.Conn = c | ||||
| 	if err = co.WriteMsg(m); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	r, err = co.ReadMsg() | ||||
| 	if err == nil && r.Id != m.Id { | ||||
| 		err = ErrId | ||||
| 	} | ||||
| 	return r, err | ||||
| } | ||||
| 
 | ||||
| // DialTimeout acts like Dial but takes a timeout. | ||||
| func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) { | ||||
| 	client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}} | ||||
| 	return client.Dial(address) | ||||
| } | ||||
| 
 | ||||
| // DialWithTLS connects to the address on the named network with TLS. | ||||
| func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) { | ||||
| 	if !strings.HasSuffix(network, "-tls") { | ||||
| 		network += "-tls" | ||||
| 	} | ||||
| 	client := Client{Net: network, TLSConfig: tlsConfig} | ||||
| 	return client.Dial(address) | ||||
| } | ||||
| 
 | ||||
| // DialTimeoutWithTLS acts like DialWithTLS but takes a timeout. | ||||
| func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) { | ||||
| 	if !strings.HasSuffix(network, "-tls") { | ||||
| 		network += "-tls" | ||||
| 	} | ||||
| 	client := Client{Net: network, Dialer: &net.Dialer{Timeout: timeout}, TLSConfig: tlsConfig} | ||||
| 	return client.Dial(address) | ||||
| } | ||||
| 
 | ||||
| // ExchangeContext acts like Exchange, but honors the deadline on the provided | ||||
| // context, if present. If there is both a context deadline and a configured | ||||
| // timeout on the client, the earliest of the two takes effect. | ||||
| func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) { | ||||
| 	conn, err := c.DialContext(ctx, a) | ||||
| 	if err != nil { | ||||
| 		return nil, 0, err | ||||
| 	} | ||||
| 	defer conn.Close() | ||||
| 
 | ||||
| 	return c.exchangeWithConnContext(ctx, m, conn) | ||||
| } | ||||
							
								
								
									
										135
									
								
								vendor/github.com/miekg/dns/clientconfig.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								vendor/github.com/miekg/dns/clientconfig.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,135 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"io" | ||||
| 	"os" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // ClientConfig wraps the contents of the /etc/resolv.conf file. | ||||
| type ClientConfig struct { | ||||
| 	Servers  []string // servers to use | ||||
| 	Search   []string // suffixes to append to local name | ||||
| 	Port     string   // what port to use | ||||
| 	Ndots    int      // number of dots in name to trigger absolute lookup | ||||
| 	Timeout  int      // seconds before giving up on packet | ||||
| 	Attempts int      // lost packets before giving up on server, not used in the package dns | ||||
| } | ||||
| 
 | ||||
| // ClientConfigFromFile parses a resolv.conf(5) like file and returns | ||||
| // a *ClientConfig. | ||||
| func ClientConfigFromFile(resolvconf string) (*ClientConfig, error) { | ||||
| 	file, err := os.Open(resolvconf) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	defer file.Close() | ||||
| 	return ClientConfigFromReader(file) | ||||
| } | ||||
| 
 | ||||
| // ClientConfigFromReader works like ClientConfigFromFile but takes an io.Reader as argument | ||||
| func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error) { | ||||
| 	c := new(ClientConfig) | ||||
| 	scanner := bufio.NewScanner(resolvconf) | ||||
| 	c.Servers = make([]string, 0) | ||||
| 	c.Search = make([]string, 0) | ||||
| 	c.Port = "53" | ||||
| 	c.Ndots = 1 | ||||
| 	c.Timeout = 5 | ||||
| 	c.Attempts = 2 | ||||
| 
 | ||||
| 	for scanner.Scan() { | ||||
| 		if err := scanner.Err(); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		line := scanner.Text() | ||||
| 		f := strings.Fields(line) | ||||
| 		if len(f) < 1 { | ||||
| 			continue | ||||
| 		} | ||||
| 		switch f[0] { | ||||
| 		case "nameserver": // add one name server | ||||
| 			if len(f) > 1 { | ||||
| 				// One more check: make sure server name is | ||||
| 				// just an IP address.  Otherwise we need DNS | ||||
| 				// to look it up. | ||||
| 				name := f[1] | ||||
| 				c.Servers = append(c.Servers, name) | ||||
| 			} | ||||
| 
 | ||||
| 		case "domain": // set search path to just this domain | ||||
| 			if len(f) > 1 { | ||||
| 				c.Search = make([]string, 1) | ||||
| 				c.Search[0] = f[1] | ||||
| 			} else { | ||||
| 				c.Search = make([]string, 0) | ||||
| 			} | ||||
| 
 | ||||
| 		case "search": // set search path to given servers | ||||
| 			c.Search = append([]string(nil), f[1:]...) | ||||
| 
 | ||||
| 		case "options": // magic options | ||||
| 			for _, s := range f[1:] { | ||||
| 				switch { | ||||
| 				case len(s) >= 6 && s[:6] == "ndots:": | ||||
| 					n, _ := strconv.Atoi(s[6:]) | ||||
| 					if n < 0 { | ||||
| 						n = 0 | ||||
| 					} else if n > 15 { | ||||
| 						n = 15 | ||||
| 					} | ||||
| 					c.Ndots = n | ||||
| 				case len(s) >= 8 && s[:8] == "timeout:": | ||||
| 					n, _ := strconv.Atoi(s[8:]) | ||||
| 					if n < 1 { | ||||
| 						n = 1 | ||||
| 					} | ||||
| 					c.Timeout = n | ||||
| 				case len(s) >= 9 && s[:9] == "attempts:": | ||||
| 					n, _ := strconv.Atoi(s[9:]) | ||||
| 					if n < 1 { | ||||
| 						n = 1 | ||||
| 					} | ||||
| 					c.Attempts = n | ||||
| 				case s == "rotate": | ||||
| 					/* not imp */ | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return c, nil | ||||
| } | ||||
| 
 | ||||
| // NameList returns all of the names that should be queried based on the | ||||
| // config. It is based off of go's net/dns name building, but it does not | ||||
| // check the length of the resulting names. | ||||
| func (c *ClientConfig) NameList(name string) []string { | ||||
| 	// if this domain is already fully qualified, no append needed. | ||||
| 	if IsFqdn(name) { | ||||
| 		return []string{name} | ||||
| 	} | ||||
| 
 | ||||
| 	// Check to see if the name has more labels than Ndots. Do this before making | ||||
| 	// the domain fully qualified. | ||||
| 	hasNdots := CountLabel(name) > c.Ndots | ||||
| 	// Make the domain fully qualified. | ||||
| 	name = Fqdn(name) | ||||
| 
 | ||||
| 	// Make a list of names based off search. | ||||
| 	names := []string{} | ||||
| 
 | ||||
| 	// If name has enough dots, try that first. | ||||
| 	if hasNdots { | ||||
| 		names = append(names, name) | ||||
| 	} | ||||
| 	for _, s := range c.Search { | ||||
| 		names = append(names, Fqdn(name+s)) | ||||
| 	} | ||||
| 	// If we didn't have enough dots, try after suffixes. | ||||
| 	if !hasNdots { | ||||
| 		names = append(names, name) | ||||
| 	} | ||||
| 	return names | ||||
| } | ||||
							
								
								
									
										43
									
								
								vendor/github.com/miekg/dns/dane.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								vendor/github.com/miekg/dns/dane.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/sha256" | ||||
| 	"crypto/sha512" | ||||
| 	"crypto/x509" | ||||
| 	"encoding/hex" | ||||
| 	"errors" | ||||
| ) | ||||
| 
 | ||||
| // CertificateToDANE converts a certificate to a hex string as used in the TLSA or SMIMEA records. | ||||
| func CertificateToDANE(selector, matchingType uint8, cert *x509.Certificate) (string, error) { | ||||
| 	switch matchingType { | ||||
| 	case 0: | ||||
| 		switch selector { | ||||
| 		case 0: | ||||
| 			return hex.EncodeToString(cert.Raw), nil | ||||
| 		case 1: | ||||
| 			return hex.EncodeToString(cert.RawSubjectPublicKeyInfo), nil | ||||
| 		} | ||||
| 	case 1: | ||||
| 		h := sha256.New() | ||||
| 		switch selector { | ||||
| 		case 0: | ||||
| 			h.Write(cert.Raw) | ||||
| 			return hex.EncodeToString(h.Sum(nil)), nil | ||||
| 		case 1: | ||||
| 			h.Write(cert.RawSubjectPublicKeyInfo) | ||||
| 			return hex.EncodeToString(h.Sum(nil)), nil | ||||
| 		} | ||||
| 	case 2: | ||||
| 		h := sha512.New() | ||||
| 		switch selector { | ||||
| 		case 0: | ||||
| 			h.Write(cert.Raw) | ||||
| 			return hex.EncodeToString(h.Sum(nil)), nil | ||||
| 		case 1: | ||||
| 			h.Write(cert.RawSubjectPublicKeyInfo) | ||||
| 			return hex.EncodeToString(h.Sum(nil)), nil | ||||
| 		} | ||||
| 	} | ||||
| 	return "", errors.New("dns: bad MatchingType or Selector") | ||||
| } | ||||
							
								
								
									
										381
									
								
								vendor/github.com/miekg/dns/defaults.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										381
									
								
								vendor/github.com/miekg/dns/defaults.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,381 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"net" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| const hexDigit = "0123456789abcdef" | ||||
| 
 | ||||
| // Everything is assumed in ClassINET. | ||||
| 
 | ||||
| // SetReply creates a reply message from a request message. | ||||
| func (dns *Msg) SetReply(request *Msg) *Msg { | ||||
| 	dns.Id = request.Id | ||||
| 	dns.Response = true | ||||
| 	dns.Opcode = request.Opcode | ||||
| 	if dns.Opcode == OpcodeQuery { | ||||
| 		dns.RecursionDesired = request.RecursionDesired // Copy rd bit | ||||
| 		dns.CheckingDisabled = request.CheckingDisabled // Copy cd bit | ||||
| 	} | ||||
| 	dns.Rcode = RcodeSuccess | ||||
| 	if len(request.Question) > 0 { | ||||
| 		dns.Question = make([]Question, 1) | ||||
| 		dns.Question[0] = request.Question[0] | ||||
| 	} | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // SetQuestion creates a question message, it sets the Question | ||||
| // section, generates an Id and sets the RecursionDesired (RD) | ||||
| // bit to true. | ||||
| func (dns *Msg) SetQuestion(z string, t uint16) *Msg { | ||||
| 	dns.Id = Id() | ||||
| 	dns.RecursionDesired = true | ||||
| 	dns.Question = make([]Question, 1) | ||||
| 	dns.Question[0] = Question{z, t, ClassINET} | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // SetNotify creates a notify message, it sets the Question | ||||
| // section, generates an Id and sets the Authoritative (AA) | ||||
| // bit to true. | ||||
| func (dns *Msg) SetNotify(z string) *Msg { | ||||
| 	dns.Opcode = OpcodeNotify | ||||
| 	dns.Authoritative = true | ||||
| 	dns.Id = Id() | ||||
| 	dns.Question = make([]Question, 1) | ||||
| 	dns.Question[0] = Question{z, TypeSOA, ClassINET} | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // SetRcode creates an error message suitable for the request. | ||||
| func (dns *Msg) SetRcode(request *Msg, rcode int) *Msg { | ||||
| 	dns.SetReply(request) | ||||
| 	dns.Rcode = rcode | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // SetRcodeFormatError creates a message with FormError set. | ||||
| func (dns *Msg) SetRcodeFormatError(request *Msg) *Msg { | ||||
| 	dns.Rcode = RcodeFormatError | ||||
| 	dns.Opcode = OpcodeQuery | ||||
| 	dns.Response = true | ||||
| 	dns.Authoritative = false | ||||
| 	dns.Id = request.Id | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // SetUpdate makes the message a dynamic update message. It | ||||
| // sets the ZONE section to: z, TypeSOA, ClassINET. | ||||
| func (dns *Msg) SetUpdate(z string) *Msg { | ||||
| 	dns.Id = Id() | ||||
| 	dns.Response = false | ||||
| 	dns.Opcode = OpcodeUpdate | ||||
| 	dns.Compress = false // BIND9 cannot handle compression | ||||
| 	dns.Question = make([]Question, 1) | ||||
| 	dns.Question[0] = Question{z, TypeSOA, ClassINET} | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // SetIxfr creates message for requesting an IXFR. | ||||
| func (dns *Msg) SetIxfr(z string, serial uint32, ns, mbox string) *Msg { | ||||
| 	dns.Id = Id() | ||||
| 	dns.Question = make([]Question, 1) | ||||
| 	dns.Ns = make([]RR, 1) | ||||
| 	s := new(SOA) | ||||
| 	s.Hdr = RR_Header{z, TypeSOA, ClassINET, defaultTtl, 0} | ||||
| 	s.Serial = serial | ||||
| 	s.Ns = ns | ||||
| 	s.Mbox = mbox | ||||
| 	dns.Question[0] = Question{z, TypeIXFR, ClassINET} | ||||
| 	dns.Ns[0] = s | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // SetAxfr creates message for requesting an AXFR. | ||||
| func (dns *Msg) SetAxfr(z string) *Msg { | ||||
| 	dns.Id = Id() | ||||
| 	dns.Question = make([]Question, 1) | ||||
| 	dns.Question[0] = Question{z, TypeAXFR, ClassINET} | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // SetTsig appends a TSIG RR to the message. | ||||
| // This is only a skeleton TSIG RR that is added as the last RR in the | ||||
| // additional section. The TSIG is calculated when the message is being send. | ||||
| func (dns *Msg) SetTsig(z, algo string, fudge uint16, timesigned int64) *Msg { | ||||
| 	t := new(TSIG) | ||||
| 	t.Hdr = RR_Header{z, TypeTSIG, ClassANY, 0, 0} | ||||
| 	t.Algorithm = algo | ||||
| 	t.Fudge = fudge | ||||
| 	t.TimeSigned = uint64(timesigned) | ||||
| 	t.OrigId = dns.Id | ||||
| 	dns.Extra = append(dns.Extra, t) | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // SetEdns0 appends a EDNS0 OPT RR to the message. | ||||
| // TSIG should always the last RR in a message. | ||||
| func (dns *Msg) SetEdns0(udpsize uint16, do bool) *Msg { | ||||
| 	e := new(OPT) | ||||
| 	e.Hdr.Name = "." | ||||
| 	e.Hdr.Rrtype = TypeOPT | ||||
| 	e.SetUDPSize(udpsize) | ||||
| 	if do { | ||||
| 		e.SetDo() | ||||
| 	} | ||||
| 	dns.Extra = append(dns.Extra, e) | ||||
| 	return dns | ||||
| } | ||||
| 
 | ||||
| // IsTsig checks if the message has a TSIG record as the last record | ||||
| // in the additional section. It returns the TSIG record found or nil. | ||||
| func (dns *Msg) IsTsig() *TSIG { | ||||
| 	if len(dns.Extra) > 0 { | ||||
| 		if dns.Extra[len(dns.Extra)-1].Header().Rrtype == TypeTSIG { | ||||
| 			return dns.Extra[len(dns.Extra)-1].(*TSIG) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // IsEdns0 checks if the message has a EDNS0 (OPT) record, any EDNS0 | ||||
| // record in the additional section will do. It returns the OPT record | ||||
| // found or nil. | ||||
| func (dns *Msg) IsEdns0() *OPT { | ||||
| 	// RFC 6891, Section 6.1.1 allows the OPT record to appear | ||||
| 	// anywhere in the additional record section, but it's usually at | ||||
| 	// the end so start there. | ||||
| 	for i := len(dns.Extra) - 1; i >= 0; i-- { | ||||
| 		if dns.Extra[i].Header().Rrtype == TypeOPT { | ||||
| 			return dns.Extra[i].(*OPT) | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // popEdns0 is like IsEdns0, but it removes the record from the message. | ||||
| func (dns *Msg) popEdns0() *OPT { | ||||
| 	// RFC 6891, Section 6.1.1 allows the OPT record to appear | ||||
| 	// anywhere in the additional record section, but it's usually at | ||||
| 	// the end so start there. | ||||
| 	for i := len(dns.Extra) - 1; i >= 0; i-- { | ||||
| 		if dns.Extra[i].Header().Rrtype == TypeOPT { | ||||
| 			opt := dns.Extra[i].(*OPT) | ||||
| 			dns.Extra = append(dns.Extra[:i], dns.Extra[i+1:]...) | ||||
| 			return opt | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // IsDomainName checks if s is a valid domain name, it returns the number of | ||||
| // labels and true, when a domain name is valid.  Note that non fully qualified | ||||
| // domain name is considered valid, in this case the last label is counted in | ||||
| // the number of labels.  When false is returned the number of labels is not | ||||
| // defined.  Also note that this function is extremely liberal; almost any | ||||
| // string is a valid domain name as the DNS is 8 bit protocol. It checks if each | ||||
| // label fits in 63 characters and that the entire name will fit into the 255 | ||||
| // octet wire format limit. | ||||
| func IsDomainName(s string) (labels int, ok bool) { | ||||
| 	// XXX: The logic in this function was copied from packDomainName and | ||||
| 	// should be kept in sync with that function. | ||||
| 
 | ||||
| 	const lenmsg = 256 | ||||
| 
 | ||||
| 	if len(s) == 0 { // Ok, for instance when dealing with update RR without any rdata. | ||||
| 		return 0, false | ||||
| 	} | ||||
| 
 | ||||
| 	s = Fqdn(s) | ||||
| 
 | ||||
| 	// Each dot ends a segment of the name. Except for escaped dots (\.), which | ||||
| 	// are normal dots. | ||||
| 
 | ||||
| 	var ( | ||||
| 		off    int | ||||
| 		begin  int | ||||
| 		wasDot bool | ||||
| 	) | ||||
| 	for i := 0; i < len(s); i++ { | ||||
| 		switch s[i] { | ||||
| 		case '\\': | ||||
| 			if off+1 > lenmsg { | ||||
| 				return labels, false | ||||
| 			} | ||||
| 
 | ||||
| 			// check for \DDD | ||||
| 			if i+3 < len(s) && isDigit(s[i+1]) && isDigit(s[i+2]) && isDigit(s[i+3]) { | ||||
| 				i += 3 | ||||
| 				begin += 3 | ||||
| 			} else { | ||||
| 				i++ | ||||
| 				begin++ | ||||
| 			} | ||||
| 
 | ||||
| 			wasDot = false | ||||
| 		case '.': | ||||
| 			if wasDot { | ||||
| 				// two dots back to back is not legal | ||||
| 				return labels, false | ||||
| 			} | ||||
| 			wasDot = true | ||||
| 
 | ||||
| 			labelLen := i - begin | ||||
| 			if labelLen >= 1<<6 { // top two bits of length must be clear | ||||
| 				return labels, false | ||||
| 			} | ||||
| 
 | ||||
| 			// off can already (we're in a loop) be bigger than lenmsg | ||||
| 			// this happens when a name isn't fully qualified | ||||
| 			off += 1 + labelLen | ||||
| 			if off > lenmsg { | ||||
| 				return labels, false | ||||
| 			} | ||||
| 
 | ||||
| 			labels++ | ||||
| 			begin = i + 1 | ||||
| 		default: | ||||
| 			wasDot = false | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return labels, true | ||||
| } | ||||
| 
 | ||||
| // IsSubDomain checks if child is indeed a child of the parent. If child and parent | ||||
| // are the same domain true is returned as well. | ||||
| func IsSubDomain(parent, child string) bool { | ||||
| 	// Entire child is contained in parent | ||||
| 	return CompareDomainName(parent, child) == CountLabel(parent) | ||||
| } | ||||
| 
 | ||||
| // IsMsg sanity checks buf and returns an error if it isn't a valid DNS packet. | ||||
| // The checking is performed on the binary payload. | ||||
| func IsMsg(buf []byte) error { | ||||
| 	// Header | ||||
| 	if len(buf) < headerSize { | ||||
| 		return errors.New("dns: bad message header") | ||||
| 	} | ||||
| 	// Header: Opcode | ||||
| 	// TODO(miek): more checks here, e.g. check all header bits. | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // IsFqdn checks if a domain name is fully qualified. | ||||
| func IsFqdn(s string) bool { | ||||
| 	s2 := strings.TrimSuffix(s, ".") | ||||
| 	if s == s2 { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	i := strings.LastIndexFunc(s2, func(r rune) bool { | ||||
| 		return r != '\\' | ||||
| 	}) | ||||
| 
 | ||||
| 	// Test whether we have an even number of escape sequences before | ||||
| 	// the dot or none. | ||||
| 	return (len(s2)-i)%2 != 0 | ||||
| } | ||||
| 
 | ||||
| // IsRRset checks if a set of RRs is a valid RRset as defined by RFC 2181. | ||||
| // This means the RRs need to have the same type, name, and class. Returns true | ||||
| // if the RR set is valid, otherwise false. | ||||
| func IsRRset(rrset []RR) bool { | ||||
| 	if len(rrset) == 0 { | ||||
| 		return false | ||||
| 	} | ||||
| 	if len(rrset) == 1 { | ||||
| 		return true | ||||
| 	} | ||||
| 	rrHeader := rrset[0].Header() | ||||
| 	rrType := rrHeader.Rrtype | ||||
| 	rrClass := rrHeader.Class | ||||
| 	rrName := rrHeader.Name | ||||
| 
 | ||||
| 	for _, rr := range rrset[1:] { | ||||
| 		curRRHeader := rr.Header() | ||||
| 		if curRRHeader.Rrtype != rrType || curRRHeader.Class != rrClass || curRRHeader.Name != rrName { | ||||
| 			// Mismatch between the records, so this is not a valid rrset for | ||||
| 			//signing/verifying | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // Fqdn return the fully qualified domain name from s. | ||||
| // If s is already fully qualified, it behaves as the identity function. | ||||
| func Fqdn(s string) string { | ||||
| 	if IsFqdn(s) { | ||||
| 		return s | ||||
| 	} | ||||
| 	return s + "." | ||||
| } | ||||
| 
 | ||||
| // CanonicalName returns the domain name in canonical form. A name in canonical | ||||
| // form is lowercase and fully qualified. See Section 6.2 in RFC 4034. | ||||
| func CanonicalName(s string) string { | ||||
| 	return strings.ToLower(Fqdn(s)) | ||||
| } | ||||
| 
 | ||||
| // Copied from the official Go code. | ||||
| 
 | ||||
| // ReverseAddr returns the in-addr.arpa. or ip6.arpa. hostname of the IP | ||||
| // address suitable for reverse DNS (PTR) record lookups or an error if it fails | ||||
| // to parse the IP address. | ||||
| func ReverseAddr(addr string) (arpa string, err error) { | ||||
| 	ip := net.ParseIP(addr) | ||||
| 	if ip == nil { | ||||
| 		return "", &Error{err: "unrecognized address: " + addr} | ||||
| 	} | ||||
| 	if v4 := ip.To4(); v4 != nil { | ||||
| 		buf := make([]byte, 0, net.IPv4len*4+len("in-addr.arpa.")) | ||||
| 		// Add it, in reverse, to the buffer | ||||
| 		for i := len(v4) - 1; i >= 0; i-- { | ||||
| 			buf = strconv.AppendInt(buf, int64(v4[i]), 10) | ||||
| 			buf = append(buf, '.') | ||||
| 		} | ||||
| 		// Append "in-addr.arpa." and return (buf already has the final .) | ||||
| 		buf = append(buf, "in-addr.arpa."...) | ||||
| 		return string(buf), nil | ||||
| 	} | ||||
| 	// Must be IPv6 | ||||
| 	buf := make([]byte, 0, net.IPv6len*4+len("ip6.arpa.")) | ||||
| 	// Add it, in reverse, to the buffer | ||||
| 	for i := len(ip) - 1; i >= 0; i-- { | ||||
| 		v := ip[i] | ||||
| 		buf = append(buf, hexDigit[v&0xF], '.', hexDigit[v>>4], '.') | ||||
| 	} | ||||
| 	// Append "ip6.arpa." and return (buf already has the final .) | ||||
| 	buf = append(buf, "ip6.arpa."...) | ||||
| 	return string(buf), nil | ||||
| } | ||||
| 
 | ||||
| // String returns the string representation for the type t. | ||||
| func (t Type) String() string { | ||||
| 	if t1, ok := TypeToString[uint16(t)]; ok { | ||||
| 		return t1 | ||||
| 	} | ||||
| 	return "TYPE" + strconv.Itoa(int(t)) | ||||
| } | ||||
| 
 | ||||
| // String returns the string representation for the class c. | ||||
| func (c Class) String() string { | ||||
| 	if s, ok := ClassToString[uint16(c)]; ok { | ||||
| 		// Only emit mnemonics when they are unambiguous, specially ANY is in both. | ||||
| 		if _, ok := StringToType[s]; !ok { | ||||
| 			return s | ||||
| 		} | ||||
| 	} | ||||
| 	return "CLASS" + strconv.Itoa(int(c)) | ||||
| } | ||||
| 
 | ||||
| // String returns the string representation for the name n. | ||||
| func (n Name) String() string { | ||||
| 	return sprintName(string(n)) | ||||
| } | ||||
							
								
								
									
										158
									
								
								vendor/github.com/miekg/dns/dns.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								vendor/github.com/miekg/dns/dns.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,158 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/hex" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	year68     = 1 << 31 // For RFC1982 (Serial Arithmetic) calculations in 32 bits. | ||||
| 	defaultTtl = 3600    // Default internal TTL. | ||||
| 
 | ||||
| 	// DefaultMsgSize is the standard default for messages larger than 512 bytes. | ||||
| 	DefaultMsgSize = 4096 | ||||
| 	// MinMsgSize is the minimal size of a DNS packet. | ||||
| 	MinMsgSize = 512 | ||||
| 	// MaxMsgSize is the largest possible DNS packet. | ||||
| 	MaxMsgSize = 65535 | ||||
| ) | ||||
| 
 | ||||
| // Error represents a DNS error. | ||||
| type Error struct{ err string } | ||||
| 
 | ||||
| func (e *Error) Error() string { | ||||
| 	if e == nil { | ||||
| 		return "dns: <nil>" | ||||
| 	} | ||||
| 	return "dns: " + e.err | ||||
| } | ||||
| 
 | ||||
| // An RR represents a resource record. | ||||
| type RR interface { | ||||
| 	// Header returns the header of an resource record. The header contains | ||||
| 	// everything up to the rdata. | ||||
| 	Header() *RR_Header | ||||
| 	// String returns the text representation of the resource record. | ||||
| 	String() string | ||||
| 
 | ||||
| 	// copy returns a copy of the RR | ||||
| 	copy() RR | ||||
| 
 | ||||
| 	// len returns the length (in octets) of the compressed or uncompressed RR in wire format. | ||||
| 	// | ||||
| 	// If compression is nil, the uncompressed size will be returned, otherwise the compressed | ||||
| 	// size will be returned and domain names will be added to the map for future compression. | ||||
| 	len(off int, compression map[string]struct{}) int | ||||
| 
 | ||||
| 	// pack packs the records RDATA into wire format. The header will | ||||
| 	// already have been packed into msg. | ||||
| 	pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) | ||||
| 
 | ||||
| 	// unpack unpacks an RR from wire format. | ||||
| 	// | ||||
| 	// This will only be called on a new and empty RR type with only the header populated. It | ||||
| 	// will only be called if the record's RDATA is non-empty. | ||||
| 	unpack(msg []byte, off int) (off1 int, err error) | ||||
| 
 | ||||
| 	// parse parses an RR from zone file format. | ||||
| 	// | ||||
| 	// This will only be called on a new and empty RR type with only the header populated. | ||||
| 	parse(c *zlexer, origin string) *ParseError | ||||
| 
 | ||||
| 	// isDuplicate returns whether the two RRs are duplicates. | ||||
| 	isDuplicate(r2 RR) bool | ||||
| } | ||||
| 
 | ||||
| // RR_Header is the header all DNS resource records share. | ||||
| type RR_Header struct { | ||||
| 	Name     string `dns:"cdomain-name"` | ||||
| 	Rrtype   uint16 | ||||
| 	Class    uint16 | ||||
| 	Ttl      uint32 | ||||
| 	Rdlength uint16 // Length of data after header. | ||||
| } | ||||
| 
 | ||||
| // Header returns itself. This is here to make RR_Header implements the RR interface. | ||||
| func (h *RR_Header) Header() *RR_Header { return h } | ||||
| 
 | ||||
| // Just to implement the RR interface. | ||||
| func (h *RR_Header) copy() RR { return nil } | ||||
| 
 | ||||
| func (h *RR_Header) String() string { | ||||
| 	var s string | ||||
| 
 | ||||
| 	if h.Rrtype == TypeOPT { | ||||
| 		s = ";" | ||||
| 		// and maybe other things | ||||
| 	} | ||||
| 
 | ||||
| 	s += sprintName(h.Name) + "\t" | ||||
| 	s += strconv.FormatInt(int64(h.Ttl), 10) + "\t" | ||||
| 	s += Class(h.Class).String() + "\t" | ||||
| 	s += Type(h.Rrtype).String() + "\t" | ||||
| 	return s | ||||
| } | ||||
| 
 | ||||
| func (h *RR_Header) len(off int, compression map[string]struct{}) int { | ||||
| 	l := domainNameLen(h.Name, off, compression, true) | ||||
| 	l += 10 // rrtype(2) + class(2) + ttl(4) + rdlength(2) | ||||
| 	return l | ||||
| } | ||||
| 
 | ||||
| func (h *RR_Header) pack(msg []byte, off int, compression compressionMap, compress bool) (off1 int, err error) { | ||||
| 	// RR_Header has no RDATA to pack. | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func (h *RR_Header) unpack(msg []byte, off int) (int, error) { | ||||
| 	panic("dns: internal error: unpack should never be called on RR_Header") | ||||
| } | ||||
| 
 | ||||
| func (h *RR_Header) parse(c *zlexer, origin string) *ParseError { | ||||
| 	panic("dns: internal error: parse should never be called on RR_Header") | ||||
| } | ||||
| 
 | ||||
| // ToRFC3597 converts a known RR to the unknown RR representation from RFC 3597. | ||||
| func (rr *RFC3597) ToRFC3597(r RR) error { | ||||
| 	buf := make([]byte, Len(r)) | ||||
| 	headerEnd, off, err := packRR(r, buf, 0, compressionMap{}, false) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	buf = buf[:off] | ||||
| 
 | ||||
| 	*rr = RFC3597{Hdr: *r.Header()} | ||||
| 	rr.Hdr.Rdlength = uint16(off - headerEnd) | ||||
| 
 | ||||
| 	if noRdata(rr.Hdr) { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = rr.unpack(buf, headerEnd) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // fromRFC3597 converts an unknown RR representation from RFC 3597 to the known RR type. | ||||
| func (rr *RFC3597) fromRFC3597(r RR) error { | ||||
| 	hdr := r.Header() | ||||
| 	*hdr = rr.Hdr | ||||
| 
 | ||||
| 	// Can't overflow uint16 as the length of Rdata is validated in (*RFC3597).parse. | ||||
| 	// We can only get here when rr was constructed with that method. | ||||
| 	hdr.Rdlength = uint16(hex.DecodedLen(len(rr.Rdata))) | ||||
| 
 | ||||
| 	if noRdata(*hdr) { | ||||
| 		// Dynamic update. | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	// rr.pack requires an extra allocation and a copy so we just decode Rdata | ||||
| 	// manually, it's simpler anyway. | ||||
| 	msg, err := hex.DecodeString(rr.Rdata) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = r.unpack(msg, 0) | ||||
| 	return err | ||||
| } | ||||
							
								
								
									
										749
									
								
								vendor/github.com/miekg/dns/dnssec.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										749
									
								
								vendor/github.com/miekg/dns/dnssec.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,749 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/ed25519" | ||||
| 	"crypto/elliptic" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/rsa" | ||||
| 	_ "crypto/sha1"   // need its init function | ||||
| 	_ "crypto/sha256" // need its init function | ||||
| 	_ "crypto/sha512" // need its init function | ||||
| 	"encoding/asn1" | ||||
| 	"encoding/binary" | ||||
| 	"encoding/hex" | ||||
| 	"math/big" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // DNSSEC encryption algorithm codes. | ||||
| const ( | ||||
| 	_ uint8 = iota | ||||
| 	RSAMD5 | ||||
| 	DH | ||||
| 	DSA | ||||
| 	_ // Skip 4, RFC 6725, section 2.1 | ||||
| 	RSASHA1 | ||||
| 	DSANSEC3SHA1 | ||||
| 	RSASHA1NSEC3SHA1 | ||||
| 	RSASHA256 | ||||
| 	_ // Skip 9, RFC 6725, section 2.1 | ||||
| 	RSASHA512 | ||||
| 	_ // Skip 11, RFC 6725, section 2.1 | ||||
| 	ECCGOST | ||||
| 	ECDSAP256SHA256 | ||||
| 	ECDSAP384SHA384 | ||||
| 	ED25519 | ||||
| 	ED448 | ||||
| 	INDIRECT   uint8 = 252 | ||||
| 	PRIVATEDNS uint8 = 253 // Private (experimental keys) | ||||
| 	PRIVATEOID uint8 = 254 | ||||
| ) | ||||
| 
 | ||||
| // AlgorithmToString is a map of algorithm IDs to algorithm names. | ||||
| var AlgorithmToString = map[uint8]string{ | ||||
| 	RSAMD5:           "RSAMD5", | ||||
| 	DH:               "DH", | ||||
| 	DSA:              "DSA", | ||||
| 	RSASHA1:          "RSASHA1", | ||||
| 	DSANSEC3SHA1:     "DSA-NSEC3-SHA1", | ||||
| 	RSASHA1NSEC3SHA1: "RSASHA1-NSEC3-SHA1", | ||||
| 	RSASHA256:        "RSASHA256", | ||||
| 	RSASHA512:        "RSASHA512", | ||||
| 	ECCGOST:          "ECC-GOST", | ||||
| 	ECDSAP256SHA256:  "ECDSAP256SHA256", | ||||
| 	ECDSAP384SHA384:  "ECDSAP384SHA384", | ||||
| 	ED25519:          "ED25519", | ||||
| 	ED448:            "ED448", | ||||
| 	INDIRECT:         "INDIRECT", | ||||
| 	PRIVATEDNS:       "PRIVATEDNS", | ||||
| 	PRIVATEOID:       "PRIVATEOID", | ||||
| } | ||||
| 
 | ||||
| // AlgorithmToHash is a map of algorithm crypto hash IDs to crypto.Hash's. | ||||
| // For newer algorithm that do their own hashing (i.e. ED25519) the returned value | ||||
| // is 0, implying no (external) hashing should occur. The non-exported identityHash is then | ||||
| // used. | ||||
| var AlgorithmToHash = map[uint8]crypto.Hash{ | ||||
| 	RSAMD5:           crypto.MD5, // Deprecated in RFC 6725 | ||||
| 	DSA:              crypto.SHA1, | ||||
| 	RSASHA1:          crypto.SHA1, | ||||
| 	RSASHA1NSEC3SHA1: crypto.SHA1, | ||||
| 	RSASHA256:        crypto.SHA256, | ||||
| 	ECDSAP256SHA256:  crypto.SHA256, | ||||
| 	ECDSAP384SHA384:  crypto.SHA384, | ||||
| 	RSASHA512:        crypto.SHA512, | ||||
| 	ED25519:          0, | ||||
| } | ||||
| 
 | ||||
| // DNSSEC hashing algorithm codes. | ||||
| const ( | ||||
| 	_      uint8 = iota | ||||
| 	SHA1         // RFC 4034 | ||||
| 	SHA256       // RFC 4509 | ||||
| 	GOST94       // RFC 5933 | ||||
| 	SHA384       // Experimental | ||||
| 	SHA512       // Experimental | ||||
| ) | ||||
| 
 | ||||
| // HashToString is a map of hash IDs to names. | ||||
| var HashToString = map[uint8]string{ | ||||
| 	SHA1:   "SHA1", | ||||
| 	SHA256: "SHA256", | ||||
| 	GOST94: "GOST94", | ||||
| 	SHA384: "SHA384", | ||||
| 	SHA512: "SHA512", | ||||
| } | ||||
| 
 | ||||
| // DNSKEY flag values. | ||||
| const ( | ||||
| 	SEP    = 1 | ||||
| 	REVOKE = 1 << 7 | ||||
| 	ZONE   = 1 << 8 | ||||
| ) | ||||
| 
 | ||||
| // The RRSIG needs to be converted to wireformat with some of the rdata (the signature) missing. | ||||
| type rrsigWireFmt struct { | ||||
| 	TypeCovered uint16 | ||||
| 	Algorithm   uint8 | ||||
| 	Labels      uint8 | ||||
| 	OrigTtl     uint32 | ||||
| 	Expiration  uint32 | ||||
| 	Inception   uint32 | ||||
| 	KeyTag      uint16 | ||||
| 	SignerName  string `dns:"domain-name"` | ||||
| 	/* No Signature */ | ||||
| } | ||||
| 
 | ||||
| // Used for converting DNSKEY's rdata to wirefmt. | ||||
| type dnskeyWireFmt struct { | ||||
| 	Flags     uint16 | ||||
| 	Protocol  uint8 | ||||
| 	Algorithm uint8 | ||||
| 	PublicKey string `dns:"base64"` | ||||
| 	/* Nothing is left out */ | ||||
| } | ||||
| 
 | ||||
| func divRoundUp(a, b int) int { | ||||
| 	return (a + b - 1) / b | ||||
| } | ||||
| 
 | ||||
| // KeyTag calculates the keytag (or key-id) of the DNSKEY. | ||||
| func (k *DNSKEY) KeyTag() uint16 { | ||||
| 	if k == nil { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	var keytag int | ||||
| 	switch k.Algorithm { | ||||
| 	case RSAMD5: | ||||
| 		// This algorithm has been deprecated, but keep this key-tag calculation. | ||||
| 		// Look at the bottom two bytes of the modules, which the last item in the pubkey. | ||||
| 		// See https://www.rfc-editor.org/errata/eid193 . | ||||
| 		modulus, _ := fromBase64([]byte(k.PublicKey)) | ||||
| 		if len(modulus) > 1 { | ||||
| 			x := binary.BigEndian.Uint16(modulus[len(modulus)-3:]) | ||||
| 			keytag = int(x) | ||||
| 		} | ||||
| 	default: | ||||
| 		keywire := new(dnskeyWireFmt) | ||||
| 		keywire.Flags = k.Flags | ||||
| 		keywire.Protocol = k.Protocol | ||||
| 		keywire.Algorithm = k.Algorithm | ||||
| 		keywire.PublicKey = k.PublicKey | ||||
| 		wire := make([]byte, DefaultMsgSize) | ||||
| 		n, err := packKeyWire(keywire, wire) | ||||
| 		if err != nil { | ||||
| 			return 0 | ||||
| 		} | ||||
| 		wire = wire[:n] | ||||
| 		for i, v := range wire { | ||||
| 			if i&1 != 0 { | ||||
| 				keytag += int(v) // must be larger than uint32 | ||||
| 			} else { | ||||
| 				keytag += int(v) << 8 | ||||
| 			} | ||||
| 		} | ||||
| 		keytag += keytag >> 16 & 0xFFFF | ||||
| 		keytag &= 0xFFFF | ||||
| 	} | ||||
| 	return uint16(keytag) | ||||
| } | ||||
| 
 | ||||
| // ToDS converts a DNSKEY record to a DS record. | ||||
| func (k *DNSKEY) ToDS(h uint8) *DS { | ||||
| 	if k == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	ds := new(DS) | ||||
| 	ds.Hdr.Name = k.Hdr.Name | ||||
| 	ds.Hdr.Class = k.Hdr.Class | ||||
| 	ds.Hdr.Rrtype = TypeDS | ||||
| 	ds.Hdr.Ttl = k.Hdr.Ttl | ||||
| 	ds.Algorithm = k.Algorithm | ||||
| 	ds.DigestType = h | ||||
| 	ds.KeyTag = k.KeyTag() | ||||
| 
 | ||||
| 	keywire := new(dnskeyWireFmt) | ||||
| 	keywire.Flags = k.Flags | ||||
| 	keywire.Protocol = k.Protocol | ||||
| 	keywire.Algorithm = k.Algorithm | ||||
| 	keywire.PublicKey = k.PublicKey | ||||
| 	wire := make([]byte, DefaultMsgSize) | ||||
| 	n, err := packKeyWire(keywire, wire) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	wire = wire[:n] | ||||
| 
 | ||||
| 	owner := make([]byte, 255) | ||||
| 	off, err1 := PackDomainName(CanonicalName(k.Hdr.Name), owner, 0, nil, false) | ||||
| 	if err1 != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	owner = owner[:off] | ||||
| 	// RFC4034: | ||||
| 	// digest = digest_algorithm( DNSKEY owner name | DNSKEY RDATA); | ||||
| 	// "|" denotes concatenation | ||||
| 	// DNSKEY RDATA = Flags | Protocol | Algorithm | Public Key. | ||||
| 
 | ||||
| 	var hash crypto.Hash | ||||
| 	switch h { | ||||
| 	case SHA1: | ||||
| 		hash = crypto.SHA1 | ||||
| 	case SHA256: | ||||
| 		hash = crypto.SHA256 | ||||
| 	case SHA384: | ||||
| 		hash = crypto.SHA384 | ||||
| 	case SHA512: | ||||
| 		hash = crypto.SHA512 | ||||
| 	default: | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	s := hash.New() | ||||
| 	s.Write(owner) | ||||
| 	s.Write(wire) | ||||
| 	ds.Digest = hex.EncodeToString(s.Sum(nil)) | ||||
| 	return ds | ||||
| } | ||||
| 
 | ||||
| // ToCDNSKEY converts a DNSKEY record to a CDNSKEY record. | ||||
| func (k *DNSKEY) ToCDNSKEY() *CDNSKEY { | ||||
| 	c := &CDNSKEY{DNSKEY: *k} | ||||
| 	c.Hdr = k.Hdr | ||||
| 	c.Hdr.Rrtype = TypeCDNSKEY | ||||
| 	return c | ||||
| } | ||||
| 
 | ||||
| // ToCDS converts a DS record to a CDS record. | ||||
| func (d *DS) ToCDS() *CDS { | ||||
| 	c := &CDS{DS: *d} | ||||
| 	c.Hdr = d.Hdr | ||||
| 	c.Hdr.Rrtype = TypeCDS | ||||
| 	return c | ||||
| } | ||||
| 
 | ||||
| // Sign signs an RRSet. The signature needs to be filled in with the values: | ||||
| // Inception, Expiration, KeyTag, SignerName and Algorithm.  The rest is copied | ||||
| // from the RRset. Sign returns a non-nill error when the signing went OK. | ||||
| // There is no check if RRSet is a proper (RFC 2181) RRSet.  If OrigTTL is non | ||||
| // zero, it is used as-is, otherwise the TTL of the RRset is used as the | ||||
| // OrigTTL. | ||||
| func (rr *RRSIG) Sign(k crypto.Signer, rrset []RR) error { | ||||
| 	if k == nil { | ||||
| 		return ErrPrivKey | ||||
| 	} | ||||
| 	// s.Inception and s.Expiration may be 0 (rollover etc.), the rest must be set | ||||
| 	if rr.KeyTag == 0 || len(rr.SignerName) == 0 || rr.Algorithm == 0 { | ||||
| 		return ErrKey | ||||
| 	} | ||||
| 
 | ||||
| 	h0 := rrset[0].Header() | ||||
| 	rr.Hdr.Rrtype = TypeRRSIG | ||||
| 	rr.Hdr.Name = h0.Name | ||||
| 	rr.Hdr.Class = h0.Class | ||||
| 	if rr.OrigTtl == 0 { // If set don't override | ||||
| 		rr.OrigTtl = h0.Ttl | ||||
| 	} | ||||
| 	rr.TypeCovered = h0.Rrtype | ||||
| 	rr.Labels = uint8(CountLabel(h0.Name)) | ||||
| 
 | ||||
| 	if strings.HasPrefix(h0.Name, "*") { | ||||
| 		rr.Labels-- // wildcard, remove from label count | ||||
| 	} | ||||
| 
 | ||||
| 	sigwire := new(rrsigWireFmt) | ||||
| 	sigwire.TypeCovered = rr.TypeCovered | ||||
| 	sigwire.Algorithm = rr.Algorithm | ||||
| 	sigwire.Labels = rr.Labels | ||||
| 	sigwire.OrigTtl = rr.OrigTtl | ||||
| 	sigwire.Expiration = rr.Expiration | ||||
| 	sigwire.Inception = rr.Inception | ||||
| 	sigwire.KeyTag = rr.KeyTag | ||||
| 	// For signing, lowercase this name | ||||
| 	sigwire.SignerName = CanonicalName(rr.SignerName) | ||||
| 
 | ||||
| 	// Create the desired binary blob | ||||
| 	signdata := make([]byte, DefaultMsgSize) | ||||
| 	n, err := packSigWire(sigwire, signdata) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	signdata = signdata[:n] | ||||
| 	wire, err := rawSignatureData(rrset, rr) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	h, cryptohash, err := hashFromAlgorithm(rr.Algorithm) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	switch rr.Algorithm { | ||||
| 	case RSAMD5, DSA, DSANSEC3SHA1: | ||||
| 		// See RFC 6944. | ||||
| 		return ErrAlg | ||||
| 	default: | ||||
| 		h.Write(signdata) | ||||
| 		h.Write(wire) | ||||
| 
 | ||||
| 		signature, err := sign(k, h.Sum(nil), cryptohash, rr.Algorithm) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 
 | ||||
| 		rr.Signature = toBase64(signature) | ||||
| 		return nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func sign(k crypto.Signer, hashed []byte, hash crypto.Hash, alg uint8) ([]byte, error) { | ||||
| 	signature, err := k.Sign(rand.Reader, hashed, hash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	switch alg { | ||||
| 	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512, ED25519: | ||||
| 		return signature, nil | ||||
| 	case ECDSAP256SHA256, ECDSAP384SHA384: | ||||
| 		ecdsaSignature := &struct { | ||||
| 			R, S *big.Int | ||||
| 		}{} | ||||
| 		if _, err := asn1.Unmarshal(signature, ecdsaSignature); err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		var intlen int | ||||
| 		switch alg { | ||||
| 		case ECDSAP256SHA256: | ||||
| 			intlen = 32 | ||||
| 		case ECDSAP384SHA384: | ||||
| 			intlen = 48 | ||||
| 		} | ||||
| 
 | ||||
| 		signature := intToBytes(ecdsaSignature.R, intlen) | ||||
| 		signature = append(signature, intToBytes(ecdsaSignature.S, intlen)...) | ||||
| 		return signature, nil | ||||
| 	default: | ||||
| 		return nil, ErrAlg | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Verify validates an RRSet with the signature and key. This is only the | ||||
| // cryptographic test, the signature validity period must be checked separately. | ||||
| // This function copies the rdata of some RRs (to lowercase domain names) for the validation to work. | ||||
| // It also checks that the Zone Key bit (RFC 4034 2.1.1) is set on the DNSKEY | ||||
| // and that the Protocol field is set to 3 (RFC 4034 2.1.2). | ||||
| func (rr *RRSIG) Verify(k *DNSKEY, rrset []RR) error { | ||||
| 	// First the easy checks | ||||
| 	if !IsRRset(rrset) { | ||||
| 		return ErrRRset | ||||
| 	} | ||||
| 	if rr.KeyTag != k.KeyTag() { | ||||
| 		return ErrKey | ||||
| 	} | ||||
| 	if rr.Hdr.Class != k.Hdr.Class { | ||||
| 		return ErrKey | ||||
| 	} | ||||
| 	if rr.Algorithm != k.Algorithm { | ||||
| 		return ErrKey | ||||
| 	} | ||||
| 	if !strings.EqualFold(rr.SignerName, k.Hdr.Name) { | ||||
| 		return ErrKey | ||||
| 	} | ||||
| 	if k.Protocol != 3 { | ||||
| 		return ErrKey | ||||
| 	} | ||||
| 	// RFC 4034 2.1.1 If bit 7 has value 0, then the DNSKEY record holds some | ||||
| 	// other type of DNS public key and MUST NOT be used to verify RRSIGs that | ||||
| 	// cover RRsets. | ||||
| 	if k.Flags&ZONE == 0 { | ||||
| 		return ErrKey | ||||
| 	} | ||||
| 
 | ||||
| 	// IsRRset checked that we have at least one RR and that the RRs in | ||||
| 	// the set have consistent type, class, and name. Also check that type and | ||||
| 	// class matches the RRSIG record. | ||||
| 	if h0 := rrset[0].Header(); h0.Class != rr.Hdr.Class || h0.Rrtype != rr.TypeCovered { | ||||
| 		return ErrRRset | ||||
| 	} | ||||
| 
 | ||||
| 	// RFC 4035 5.3.2.  Reconstructing the Signed Data | ||||
| 	// Copy the sig, except the rrsig data | ||||
| 	sigwire := new(rrsigWireFmt) | ||||
| 	sigwire.TypeCovered = rr.TypeCovered | ||||
| 	sigwire.Algorithm = rr.Algorithm | ||||
| 	sigwire.Labels = rr.Labels | ||||
| 	sigwire.OrigTtl = rr.OrigTtl | ||||
| 	sigwire.Expiration = rr.Expiration | ||||
| 	sigwire.Inception = rr.Inception | ||||
| 	sigwire.KeyTag = rr.KeyTag | ||||
| 	sigwire.SignerName = CanonicalName(rr.SignerName) | ||||
| 	// Create the desired binary blob | ||||
| 	signeddata := make([]byte, DefaultMsgSize) | ||||
| 	n, err := packSigWire(sigwire, signeddata) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	signeddata = signeddata[:n] | ||||
| 	wire, err := rawSignatureData(rrset, rr) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	sigbuf := rr.sigBuf()           // Get the binary signature data | ||||
| 	if rr.Algorithm == PRIVATEDNS { // PRIVATEOID | ||||
| 		// TODO(miek) | ||||
| 		// remove the domain name and assume its ours? | ||||
| 	} | ||||
| 
 | ||||
| 	h, cryptohash, err := hashFromAlgorithm(rr.Algorithm) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	switch rr.Algorithm { | ||||
| 	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512: | ||||
| 		// TODO(mg): this can be done quicker, ie. cache the pubkey data somewhere?? | ||||
| 		pubkey := k.publicKeyRSA() // Get the key | ||||
| 		if pubkey == nil { | ||||
| 			return ErrKey | ||||
| 		} | ||||
| 
 | ||||
| 		h.Write(signeddata) | ||||
| 		h.Write(wire) | ||||
| 		return rsa.VerifyPKCS1v15(pubkey, cryptohash, h.Sum(nil), sigbuf) | ||||
| 
 | ||||
| 	case ECDSAP256SHA256, ECDSAP384SHA384: | ||||
| 		pubkey := k.publicKeyECDSA() | ||||
| 		if pubkey == nil { | ||||
| 			return ErrKey | ||||
| 		} | ||||
| 
 | ||||
| 		// Split sigbuf into the r and s coordinates | ||||
| 		r := new(big.Int).SetBytes(sigbuf[:len(sigbuf)/2]) | ||||
| 		s := new(big.Int).SetBytes(sigbuf[len(sigbuf)/2:]) | ||||
| 
 | ||||
| 		h.Write(signeddata) | ||||
| 		h.Write(wire) | ||||
| 		if ecdsa.Verify(pubkey, h.Sum(nil), r, s) { | ||||
| 			return nil | ||||
| 		} | ||||
| 		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 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // ValidityPeriod uses RFC1982 serial arithmetic to calculate | ||||
| // if a signature period is valid. If t is the zero time, the | ||||
| // current time is taken other t is. Returns true if the signature | ||||
| // is valid at the given time, otherwise returns false. | ||||
| func (rr *RRSIG) ValidityPeriod(t time.Time) bool { | ||||
| 	var utc int64 | ||||
| 	if t.IsZero() { | ||||
| 		utc = time.Now().UTC().Unix() | ||||
| 	} else { | ||||
| 		utc = t.UTC().Unix() | ||||
| 	} | ||||
| 	modi := (int64(rr.Inception) - utc) / year68 | ||||
| 	mode := (int64(rr.Expiration) - utc) / year68 | ||||
| 	ti := int64(rr.Inception) + modi*year68 | ||||
| 	te := int64(rr.Expiration) + mode*year68 | ||||
| 	return ti <= utc && utc <= te | ||||
| } | ||||
| 
 | ||||
| // Return the signatures base64 encoding sigdata as a byte slice. | ||||
| func (rr *RRSIG) sigBuf() []byte { | ||||
| 	sigbuf, err := fromBase64([]byte(rr.Signature)) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return sigbuf | ||||
| } | ||||
| 
 | ||||
| // publicKeyRSA returns the RSA public key from a DNSKEY record. | ||||
| func (k *DNSKEY) publicKeyRSA() *rsa.PublicKey { | ||||
| 	keybuf, err := fromBase64([]byte(k.PublicKey)) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if len(keybuf) < 1+1+64 { | ||||
| 		// Exponent must be at least 1 byte and modulus at least 64 | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	// RFC 2537/3110, section 2. RSA Public KEY Resource Records | ||||
| 	// Length is in the 0th byte, unless its zero, then it | ||||
| 	// it in bytes 1 and 2 and its a 16 bit number | ||||
| 	explen := uint16(keybuf[0]) | ||||
| 	keyoff := 1 | ||||
| 	if explen == 0 { | ||||
| 		explen = uint16(keybuf[1])<<8 | uint16(keybuf[2]) | ||||
| 		keyoff = 3 | ||||
| 	} | ||||
| 
 | ||||
| 	if explen > 4 || explen == 0 || keybuf[keyoff] == 0 { | ||||
| 		// Exponent larger than supported by the crypto package, | ||||
| 		// empty, or contains prohibited leading zero. | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	modoff := keyoff + int(explen) | ||||
| 	modlen := len(keybuf) - modoff | ||||
| 	if modlen < 64 || modlen > 512 || keybuf[modoff] == 0 { | ||||
| 		// Modulus is too small, large, or contains prohibited leading zero. | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	pubkey := new(rsa.PublicKey) | ||||
| 
 | ||||
| 	var expo uint64 | ||||
| 	// The exponent of length explen is between keyoff and modoff. | ||||
| 	for _, v := range keybuf[keyoff:modoff] { | ||||
| 		expo <<= 8 | ||||
| 		expo |= uint64(v) | ||||
| 	} | ||||
| 	if expo > 1<<31-1 { | ||||
| 		// Larger exponent than supported by the crypto package. | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	pubkey.E = int(expo) | ||||
| 	pubkey.N = new(big.Int).SetBytes(keybuf[modoff:]) | ||||
| 	return pubkey | ||||
| } | ||||
| 
 | ||||
| // publicKeyECDSA returns the Curve public key from the DNSKEY record. | ||||
| func (k *DNSKEY) publicKeyECDSA() *ecdsa.PublicKey { | ||||
| 	keybuf, err := fromBase64([]byte(k.PublicKey)) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	pubkey := new(ecdsa.PublicKey) | ||||
| 	switch k.Algorithm { | ||||
| 	case ECDSAP256SHA256: | ||||
| 		pubkey.Curve = elliptic.P256() | ||||
| 		if len(keybuf) != 64 { | ||||
| 			// wrongly encoded key | ||||
| 			return nil | ||||
| 		} | ||||
| 	case ECDSAP384SHA384: | ||||
| 		pubkey.Curve = elliptic.P384() | ||||
| 		if len(keybuf) != 96 { | ||||
| 			// Wrongly encoded key | ||||
| 			return nil | ||||
| 		} | ||||
| 	} | ||||
| 	pubkey.X = new(big.Int).SetBytes(keybuf[:len(keybuf)/2]) | ||||
| 	pubkey.Y = new(big.Int).SetBytes(keybuf[len(keybuf)/2:]) | ||||
| 	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) } | ||||
| func (p wireSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } | ||||
| func (p wireSlice) Less(i, j int) bool { | ||||
| 	_, ioff, _ := UnpackDomainName(p[i], 0) | ||||
| 	_, joff, _ := UnpackDomainName(p[j], 0) | ||||
| 	return bytes.Compare(p[i][ioff+10:], p[j][joff+10:]) < 0 | ||||
| } | ||||
| 
 | ||||
| // Return the raw signature data. | ||||
| func rawSignatureData(rrset []RR, s *RRSIG) (buf []byte, err error) { | ||||
| 	wires := make(wireSlice, len(rrset)) | ||||
| 	for i, r := range rrset { | ||||
| 		r1 := r.copy() | ||||
| 		h := r1.Header() | ||||
| 		h.Ttl = s.OrigTtl | ||||
| 		labels := SplitDomainName(h.Name) | ||||
| 		// 6.2. Canonical RR Form. (4) - wildcards | ||||
| 		if len(labels) > int(s.Labels) { | ||||
| 			// Wildcard | ||||
| 			h.Name = "*." + strings.Join(labels[len(labels)-int(s.Labels):], ".") + "." | ||||
| 		} | ||||
| 		// RFC 4034: 6.2.  Canonical RR Form. (2) - domain name to lowercase | ||||
| 		h.Name = CanonicalName(h.Name) | ||||
| 		// 6.2. Canonical RR Form. (3) - domain rdata to lowercase. | ||||
| 		//   NS, MD, MF, CNAME, SOA, MB, MG, MR, PTR, | ||||
| 		//   HINFO, MINFO, MX, RP, AFSDB, RT, SIG, PX, NXT, NAPTR, KX, | ||||
| 		//   SRV, DNAME, A6 | ||||
| 		// | ||||
| 		// RFC 6840 - Clarifications and Implementation Notes for DNS Security (DNSSEC): | ||||
| 		//	Section 6.2 of [RFC4034] also erroneously lists HINFO as a record | ||||
| 		//	that needs conversion to lowercase, and twice at that.  Since HINFO | ||||
| 		//	records contain no domain names, they are not subject to case | ||||
| 		//	conversion. | ||||
| 		switch x := r1.(type) { | ||||
| 		case *NS: | ||||
| 			x.Ns = CanonicalName(x.Ns) | ||||
| 		case *MD: | ||||
| 			x.Md = CanonicalName(x.Md) | ||||
| 		case *MF: | ||||
| 			x.Mf = CanonicalName(x.Mf) | ||||
| 		case *CNAME: | ||||
| 			x.Target = CanonicalName(x.Target) | ||||
| 		case *SOA: | ||||
| 			x.Ns = CanonicalName(x.Ns) | ||||
| 			x.Mbox = CanonicalName(x.Mbox) | ||||
| 		case *MB: | ||||
| 			x.Mb = CanonicalName(x.Mb) | ||||
| 		case *MG: | ||||
| 			x.Mg = CanonicalName(x.Mg) | ||||
| 		case *MR: | ||||
| 			x.Mr = CanonicalName(x.Mr) | ||||
| 		case *PTR: | ||||
| 			x.Ptr = CanonicalName(x.Ptr) | ||||
| 		case *MINFO: | ||||
| 			x.Rmail = CanonicalName(x.Rmail) | ||||
| 			x.Email = CanonicalName(x.Email) | ||||
| 		case *MX: | ||||
| 			x.Mx = CanonicalName(x.Mx) | ||||
| 		case *RP: | ||||
| 			x.Mbox = CanonicalName(x.Mbox) | ||||
| 			x.Txt = CanonicalName(x.Txt) | ||||
| 		case *AFSDB: | ||||
| 			x.Hostname = CanonicalName(x.Hostname) | ||||
| 		case *RT: | ||||
| 			x.Host = CanonicalName(x.Host) | ||||
| 		case *SIG: | ||||
| 			x.SignerName = CanonicalName(x.SignerName) | ||||
| 		case *PX: | ||||
| 			x.Map822 = CanonicalName(x.Map822) | ||||
| 			x.Mapx400 = CanonicalName(x.Mapx400) | ||||
| 		case *NAPTR: | ||||
| 			x.Replacement = CanonicalName(x.Replacement) | ||||
| 		case *KX: | ||||
| 			x.Exchanger = CanonicalName(x.Exchanger) | ||||
| 		case *SRV: | ||||
| 			x.Target = CanonicalName(x.Target) | ||||
| 		case *DNAME: | ||||
| 			x.Target = CanonicalName(x.Target) | ||||
| 		} | ||||
| 		// 6.2. Canonical RR Form. (5) - origTTL | ||||
| 		wire := make([]byte, Len(r1)+1) // +1 to be safe(r) | ||||
| 		off, err1 := PackRR(r1, wire, 0, nil, false) | ||||
| 		if err1 != nil { | ||||
| 			return nil, err1 | ||||
| 		} | ||||
| 		wire = wire[:off] | ||||
| 		wires[i] = wire | ||||
| 	} | ||||
| 	sort.Sort(wires) | ||||
| 	for i, wire := range wires { | ||||
| 		if i > 0 && bytes.Equal(wire, wires[i-1]) { | ||||
| 			continue | ||||
| 		} | ||||
| 		buf = append(buf, wire...) | ||||
| 	} | ||||
| 	return buf, nil | ||||
| } | ||||
| 
 | ||||
| func packSigWire(sw *rrsigWireFmt, msg []byte) (int, error) { | ||||
| 	// copied from zmsg.go RRSIG packing | ||||
| 	off, err := packUint16(sw.TypeCovered, msg, 0) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint8(sw.Algorithm, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint8(sw.Labels, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint32(sw.OrigTtl, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint32(sw.Expiration, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint32(sw.Inception, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint16(sw.KeyTag, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = PackDomainName(sw.SignerName, msg, off, nil, false) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func packKeyWire(dw *dnskeyWireFmt, msg []byte) (int, error) { | ||||
| 	// copied from zmsg.go DNSKEY packing | ||||
| 	off, err := packUint16(dw.Flags, msg, 0) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint8(dw.Protocol, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint8(dw.Algorithm, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packStringBase64(dw.PublicKey, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
							
								
								
									
										139
									
								
								vendor/github.com/miekg/dns/dnssec_keygen.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								vendor/github.com/miekg/dns/dnssec_keygen.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,139 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/ed25519" | ||||
| 	"crypto/elliptic" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/rsa" | ||||
| 	"math/big" | ||||
| ) | ||||
| 
 | ||||
| // Generate generates a DNSKEY of the given bit size. | ||||
| // The public part is put inside the DNSKEY record. | ||||
| // The Algorithm in the key must be set as this will define | ||||
| // what kind of DNSKEY will be generated. | ||||
| // The ECDSA algorithms imply a fixed keysize, in that case | ||||
| // bits should be set to the size of the algorithm. | ||||
| func (k *DNSKEY) Generate(bits int) (crypto.PrivateKey, error) { | ||||
| 	switch k.Algorithm { | ||||
| 	case RSASHA1, RSASHA256, RSASHA1NSEC3SHA1: | ||||
| 		if bits < 512 || bits > 4096 { | ||||
| 			return nil, ErrKeySize | ||||
| 		} | ||||
| 	case RSASHA512: | ||||
| 		if bits < 1024 || bits > 4096 { | ||||
| 			return nil, ErrKeySize | ||||
| 		} | ||||
| 	case ECDSAP256SHA256: | ||||
| 		if bits != 256 { | ||||
| 			return nil, ErrKeySize | ||||
| 		} | ||||
| 	case ECDSAP384SHA384: | ||||
| 		if bits != 384 { | ||||
| 			return nil, ErrKeySize | ||||
| 		} | ||||
| 	case ED25519: | ||||
| 		if bits != 256 { | ||||
| 			return nil, ErrKeySize | ||||
| 		} | ||||
| 	default: | ||||
| 		return nil, ErrAlg | ||||
| 	} | ||||
| 
 | ||||
| 	switch k.Algorithm { | ||||
| 	case RSASHA1, RSASHA256, RSASHA512, RSASHA1NSEC3SHA1: | ||||
| 		priv, err := rsa.GenerateKey(rand.Reader, bits) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		k.setPublicKeyRSA(priv.PublicKey.E, priv.PublicKey.N) | ||||
| 		return priv, nil | ||||
| 	case ECDSAP256SHA256, ECDSAP384SHA384: | ||||
| 		var c elliptic.Curve | ||||
| 		switch k.Algorithm { | ||||
| 		case ECDSAP256SHA256: | ||||
| 			c = elliptic.P256() | ||||
| 		case ECDSAP384SHA384: | ||||
| 			c = elliptic.P384() | ||||
| 		} | ||||
| 		priv, err := ecdsa.GenerateKey(c, rand.Reader) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		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 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Set the public key (the value E and N) | ||||
| func (k *DNSKEY) setPublicKeyRSA(_E int, _N *big.Int) bool { | ||||
| 	if _E == 0 || _N == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	buf := exponentToBuf(_E) | ||||
| 	buf = append(buf, _N.Bytes()...) | ||||
| 	k.PublicKey = toBase64(buf) | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // Set the public key for Elliptic Curves | ||||
| func (k *DNSKEY) setPublicKeyECDSA(_X, _Y *big.Int) bool { | ||||
| 	if _X == nil || _Y == nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	var intlen int | ||||
| 	switch k.Algorithm { | ||||
| 	case ECDSAP256SHA256: | ||||
| 		intlen = 32 | ||||
| 	case ECDSAP384SHA384: | ||||
| 		intlen = 48 | ||||
| 	} | ||||
| 	k.PublicKey = toBase64(curveToBuf(_X, _Y, intlen)) | ||||
| 	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 { | ||||
| 	var buf []byte | ||||
| 	i := big.NewInt(int64(_E)).Bytes() | ||||
| 	if len(i) < 256 { | ||||
| 		buf = make([]byte, 1, 1+len(i)) | ||||
| 		buf[0] = uint8(len(i)) | ||||
| 	} else { | ||||
| 		buf = make([]byte, 3, 3+len(i)) | ||||
| 		buf[0] = 0 | ||||
| 		buf[1] = uint8(len(i) >> 8) | ||||
| 		buf[2] = uint8(len(i)) | ||||
| 	} | ||||
| 	buf = append(buf, i...) | ||||
| 	return buf | ||||
| } | ||||
| 
 | ||||
| // Set the public key for X and Y for Curve. The two | ||||
| // values are just concatenated. | ||||
| func curveToBuf(_X, _Y *big.Int, intlen int) []byte { | ||||
| 	buf := intToBytes(_X, intlen) | ||||
| 	buf = append(buf, intToBytes(_Y, intlen)...) | ||||
| 	return buf | ||||
| } | ||||
							
								
								
									
										309
									
								
								vendor/github.com/miekg/dns/dnssec_keyscan.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										309
									
								
								vendor/github.com/miekg/dns/dnssec_keyscan.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,309 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"bufio" | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/ed25519" | ||||
| 	"crypto/rsa" | ||||
| 	"io" | ||||
| 	"math/big" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // NewPrivateKey returns a PrivateKey by parsing the string s. | ||||
| // s should be in the same form of the BIND private key files. | ||||
| func (k *DNSKEY) NewPrivateKey(s string) (crypto.PrivateKey, error) { | ||||
| 	if s == "" || s[len(s)-1] != '\n' { // We need a closing newline | ||||
| 		return k.ReadPrivateKey(strings.NewReader(s+"\n"), "") | ||||
| 	} | ||||
| 	return k.ReadPrivateKey(strings.NewReader(s), "") | ||||
| } | ||||
| 
 | ||||
| // ReadPrivateKey reads a private key from the io.Reader q. The string file is | ||||
| // only used in error reporting. | ||||
| // The public key must be known, because some cryptographic algorithms embed | ||||
| // the public inside the privatekey. | ||||
| func (k *DNSKEY) ReadPrivateKey(q io.Reader, file string) (crypto.PrivateKey, error) { | ||||
| 	m, err := parseKey(q, file) | ||||
| 	if m == nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if _, ok := m["private-key-format"]; !ok { | ||||
| 		return nil, ErrPrivKey | ||||
| 	} | ||||
| 	if m["private-key-format"] != "v1.2" && m["private-key-format"] != "v1.3" { | ||||
| 		return nil, ErrPrivKey | ||||
| 	} | ||||
| 	// TODO(mg): check if the pubkey matches the private key | ||||
| 	algo, err := strconv.ParseUint(strings.SplitN(m["algorithm"], " ", 2)[0], 10, 8) | ||||
| 	if err != nil { | ||||
| 		return nil, ErrPrivKey | ||||
| 	} | ||||
| 	switch uint8(algo) { | ||||
| 	case RSASHA1, RSASHA1NSEC3SHA1, RSASHA256, RSASHA512: | ||||
| 		priv, err := readPrivateKeyRSA(m) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		pub := k.publicKeyRSA() | ||||
| 		if pub == nil { | ||||
| 			return nil, ErrKey | ||||
| 		} | ||||
| 		priv.PublicKey = *pub | ||||
| 		return priv, nil | ||||
| 	case ECDSAP256SHA256, ECDSAP384SHA384: | ||||
| 		priv, err := readPrivateKeyECDSA(m) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		pub := k.publicKeyECDSA() | ||||
| 		if pub == nil { | ||||
| 			return nil, ErrKey | ||||
| 		} | ||||
| 		priv.PublicKey = *pub | ||||
| 		return priv, nil | ||||
| 	case ED25519: | ||||
| 		return readPrivateKeyED25519(m) | ||||
| 	default: | ||||
| 		return nil, ErrAlg | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Read a private key (file) string and create a public key. Return the private key. | ||||
| func readPrivateKeyRSA(m map[string]string) (*rsa.PrivateKey, error) { | ||||
| 	p := new(rsa.PrivateKey) | ||||
| 	p.Primes = []*big.Int{nil, nil} | ||||
| 	for k, v := range m { | ||||
| 		switch k { | ||||
| 		case "modulus", "publicexponent", "privateexponent", "prime1", "prime2": | ||||
| 			v1, err := fromBase64([]byte(v)) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			switch k { | ||||
| 			case "modulus": | ||||
| 				p.PublicKey.N = new(big.Int).SetBytes(v1) | ||||
| 			case "publicexponent": | ||||
| 				i := new(big.Int).SetBytes(v1) | ||||
| 				p.PublicKey.E = int(i.Int64()) // int64 should be large enough | ||||
| 			case "privateexponent": | ||||
| 				p.D = new(big.Int).SetBytes(v1) | ||||
| 			case "prime1": | ||||
| 				p.Primes[0] = new(big.Int).SetBytes(v1) | ||||
| 			case "prime2": | ||||
| 				p.Primes[1] = new(big.Int).SetBytes(v1) | ||||
| 			} | ||||
| 		case "exponent1", "exponent2", "coefficient": | ||||
| 			// not used in Go (yet) | ||||
| 		case "created", "publish", "activate": | ||||
| 			// not used in Go (yet) | ||||
| 		} | ||||
| 	} | ||||
| 	return p, nil | ||||
| } | ||||
| 
 | ||||
| func readPrivateKeyECDSA(m map[string]string) (*ecdsa.PrivateKey, error) { | ||||
| 	p := new(ecdsa.PrivateKey) | ||||
| 	p.D = new(big.Int) | ||||
| 	// TODO: validate that the required flags are present | ||||
| 	for k, v := range m { | ||||
| 		switch k { | ||||
| 		case "privatekey": | ||||
| 			v1, err := fromBase64([]byte(v)) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			p.D.SetBytes(v1) | ||||
| 		case "created", "publish", "activate": | ||||
| 			/* not used in Go (yet) */ | ||||
| 		} | ||||
| 	} | ||||
| 	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) != ed25519.SeedSize { | ||||
| 				return nil, ErrPrivKey | ||||
| 			} | ||||
| 			p = ed25519.NewKeyFromSeed(p1) | ||||
| 		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) { | ||||
| 	m := make(map[string]string) | ||||
| 	var k string | ||||
| 
 | ||||
| 	c := newKLexer(r) | ||||
| 
 | ||||
| 	for l, ok := c.Next(); ok; l, ok = c.Next() { | ||||
| 		// It should alternate | ||||
| 		switch l.value { | ||||
| 		case zKey: | ||||
| 			k = l.token | ||||
| 		case zValue: | ||||
| 			if k == "" { | ||||
| 				return nil, &ParseError{file, "no private key seen", l} | ||||
| 			} | ||||
| 
 | ||||
| 			m[strings.ToLower(k)] = l.token | ||||
| 			k = "" | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Surface any read errors from r. | ||||
| 	if err := c.Err(); err != nil { | ||||
| 		return nil, &ParseError{file: file, err: err.Error()} | ||||
| 	} | ||||
| 
 | ||||
| 	return m, nil | ||||
| } | ||||
| 
 | ||||
| type klexer struct { | ||||
| 	br io.ByteReader | ||||
| 
 | ||||
| 	readErr error | ||||
| 
 | ||||
| 	line   int | ||||
| 	column int | ||||
| 
 | ||||
| 	key bool | ||||
| 
 | ||||
| 	eol bool // end-of-line | ||||
| } | ||||
| 
 | ||||
| func newKLexer(r io.Reader) *klexer { | ||||
| 	br, ok := r.(io.ByteReader) | ||||
| 	if !ok { | ||||
| 		br = bufio.NewReaderSize(r, 1024) | ||||
| 	} | ||||
| 
 | ||||
| 	return &klexer{ | ||||
| 		br: br, | ||||
| 
 | ||||
| 		line: 1, | ||||
| 
 | ||||
| 		key: true, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (kl *klexer) Err() error { | ||||
| 	if kl.readErr == io.EOF { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return kl.readErr | ||||
| } | ||||
| 
 | ||||
| // readByte returns the next byte from the input | ||||
| func (kl *klexer) readByte() (byte, bool) { | ||||
| 	if kl.readErr != nil { | ||||
| 		return 0, false | ||||
| 	} | ||||
| 
 | ||||
| 	c, err := kl.br.ReadByte() | ||||
| 	if err != nil { | ||||
| 		kl.readErr = err | ||||
| 		return 0, false | ||||
| 	} | ||||
| 
 | ||||
| 	// delay the newline handling until the next token is delivered, | ||||
| 	// fixes off-by-one errors when reporting a parse error. | ||||
| 	if kl.eol { | ||||
| 		kl.line++ | ||||
| 		kl.column = 0 | ||||
| 		kl.eol = false | ||||
| 	} | ||||
| 
 | ||||
| 	if c == '\n' { | ||||
| 		kl.eol = true | ||||
| 	} else { | ||||
| 		kl.column++ | ||||
| 	} | ||||
| 
 | ||||
| 	return c, true | ||||
| } | ||||
| 
 | ||||
| func (kl *klexer) Next() (lex, bool) { | ||||
| 	var ( | ||||
| 		l lex | ||||
| 
 | ||||
| 		str strings.Builder | ||||
| 
 | ||||
| 		commt bool | ||||
| 	) | ||||
| 
 | ||||
| 	for x, ok := kl.readByte(); ok; x, ok = kl.readByte() { | ||||
| 		l.line, l.column = kl.line, kl.column | ||||
| 
 | ||||
| 		switch x { | ||||
| 		case ':': | ||||
| 			if commt || !kl.key { | ||||
| 				break | ||||
| 			} | ||||
| 
 | ||||
| 			kl.key = false | ||||
| 
 | ||||
| 			// Next token is a space, eat it | ||||
| 			kl.readByte() | ||||
| 
 | ||||
| 			l.value = zKey | ||||
| 			l.token = str.String() | ||||
| 			return l, true | ||||
| 		case ';': | ||||
| 			commt = true | ||||
| 		case '\n': | ||||
| 			if commt { | ||||
| 				// Reset a comment | ||||
| 				commt = false | ||||
| 			} | ||||
| 
 | ||||
| 			if kl.key && str.Len() == 0 { | ||||
| 				// ignore empty lines | ||||
| 				break | ||||
| 			} | ||||
| 
 | ||||
| 			kl.key = true | ||||
| 
 | ||||
| 			l.value = zValue | ||||
| 			l.token = str.String() | ||||
| 			return l, true | ||||
| 		default: | ||||
| 			if commt { | ||||
| 				break | ||||
| 			} | ||||
| 
 | ||||
| 			str.WriteByte(x) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if kl.readErr != nil && kl.readErr != io.EOF { | ||||
| 		// Don't return any tokens after a read error occurs. | ||||
| 		return lex{value: zEOF}, false | ||||
| 	} | ||||
| 
 | ||||
| 	if str.Len() > 0 { | ||||
| 		// Send remainder | ||||
| 		l.value = zValue | ||||
| 		l.token = str.String() | ||||
| 		return l, true | ||||
| 	} | ||||
| 
 | ||||
| 	return lex{value: zEOF}, false | ||||
| } | ||||
							
								
								
									
										77
									
								
								vendor/github.com/miekg/dns/dnssec_privkey.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								vendor/github.com/miekg/dns/dnssec_privkey.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/ed25519" | ||||
| 	"crypto/rsa" | ||||
| 	"math/big" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| const format = "Private-key-format: v1.3\n" | ||||
| 
 | ||||
| var bigIntOne = big.NewInt(1) | ||||
| 
 | ||||
| // PrivateKeyString converts a PrivateKey to a string. This string has the same | ||||
| // format as the private-key-file of BIND9 (Private-key-format: v1.3). | ||||
| // It needs some info from the key (the algorithm), so its a method of the DNSKEY. | ||||
| // It supports *rsa.PrivateKey, *ecdsa.PrivateKey and ed25519.PrivateKey. | ||||
| func (r *DNSKEY) PrivateKeyString(p crypto.PrivateKey) string { | ||||
| 	algorithm := strconv.Itoa(int(r.Algorithm)) | ||||
| 	algorithm += " (" + AlgorithmToString[r.Algorithm] + ")" | ||||
| 
 | ||||
| 	switch p := p.(type) { | ||||
| 	case *rsa.PrivateKey: | ||||
| 		modulus := toBase64(p.PublicKey.N.Bytes()) | ||||
| 		e := big.NewInt(int64(p.PublicKey.E)) | ||||
| 		publicExponent := toBase64(e.Bytes()) | ||||
| 		privateExponent := toBase64(p.D.Bytes()) | ||||
| 		prime1 := toBase64(p.Primes[0].Bytes()) | ||||
| 		prime2 := toBase64(p.Primes[1].Bytes()) | ||||
| 		// Calculate Exponent1/2 and Coefficient as per: http://en.wikipedia.org/wiki/RSA#Using_the_Chinese_remainder_algorithm | ||||
| 		// and from: http://code.google.com/p/go/issues/detail?id=987 | ||||
| 		p1 := new(big.Int).Sub(p.Primes[0], bigIntOne) | ||||
| 		q1 := new(big.Int).Sub(p.Primes[1], bigIntOne) | ||||
| 		exp1 := new(big.Int).Mod(p.D, p1) | ||||
| 		exp2 := new(big.Int).Mod(p.D, q1) | ||||
| 		coeff := new(big.Int).ModInverse(p.Primes[1], p.Primes[0]) | ||||
| 
 | ||||
| 		exponent1 := toBase64(exp1.Bytes()) | ||||
| 		exponent2 := toBase64(exp2.Bytes()) | ||||
| 		coefficient := toBase64(coeff.Bytes()) | ||||
| 
 | ||||
| 		return format + | ||||
| 			"Algorithm: " + algorithm + "\n" + | ||||
| 			"Modulus: " + modulus + "\n" + | ||||
| 			"PublicExponent: " + publicExponent + "\n" + | ||||
| 			"PrivateExponent: " + privateExponent + "\n" + | ||||
| 			"Prime1: " + prime1 + "\n" + | ||||
| 			"Prime2: " + prime2 + "\n" + | ||||
| 			"Exponent1: " + exponent1 + "\n" + | ||||
| 			"Exponent2: " + exponent2 + "\n" + | ||||
| 			"Coefficient: " + coefficient + "\n" | ||||
| 
 | ||||
| 	case *ecdsa.PrivateKey: | ||||
| 		var intlen int | ||||
| 		switch r.Algorithm { | ||||
| 		case ECDSAP256SHA256: | ||||
| 			intlen = 32 | ||||
| 		case ECDSAP384SHA384: | ||||
| 			intlen = 48 | ||||
| 		} | ||||
| 		private := toBase64(intToBytes(p.D, intlen)) | ||||
| 		return format + | ||||
| 			"Algorithm: " + algorithm + "\n" + | ||||
| 			"PrivateKey: " + private + "\n" | ||||
| 
 | ||||
| 	case ed25519.PrivateKey: | ||||
| 		private := toBase64(p.Seed()) | ||||
| 		return format + | ||||
| 			"Algorithm: " + algorithm + "\n" + | ||||
| 			"PrivateKey: " + private + "\n" | ||||
| 
 | ||||
| 	default: | ||||
| 		return "" | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										292
									
								
								vendor/github.com/miekg/dns/doc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								vendor/github.com/miekg/dns/doc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,292 @@ | |||
| /* | ||||
| Package dns implements a full featured interface to the Domain Name System. | ||||
| Both server- and client-side programming is supported. The package allows | ||||
| complete control over what is sent out to the DNS. The API follows the | ||||
| less-is-more principle, by presenting a small, clean interface. | ||||
| 
 | ||||
| It supports (asynchronous) querying/replying, incoming/outgoing zone transfers, | ||||
| TSIG, EDNS0, dynamic updates, notifies and DNSSEC validation/signing. | ||||
| 
 | ||||
| Note that domain names MUST be fully qualified before sending them, unqualified | ||||
| names in a message will result in a packing failure. | ||||
| 
 | ||||
| Resource records are native types. They are not stored in wire format. Basic | ||||
| usage pattern for creating a new resource record: | ||||
| 
 | ||||
|      r := new(dns.MX) | ||||
|      r.Hdr = dns.RR_Header{Name: "miek.nl.", Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: 3600} | ||||
|      r.Preference = 10 | ||||
|      r.Mx = "mx.miek.nl." | ||||
| 
 | ||||
| Or directly from a string: | ||||
| 
 | ||||
|      mx, err := dns.NewRR("miek.nl. 3600 IN MX 10 mx.miek.nl.") | ||||
| 
 | ||||
| Or when the default origin (.) and TTL (3600) and class (IN) suit you: | ||||
| 
 | ||||
|      mx, err := dns.NewRR("miek.nl MX 10 mx.miek.nl") | ||||
| 
 | ||||
| Or even: | ||||
| 
 | ||||
|      mx, err := dns.NewRR("$ORIGIN nl.\nmiek 1H IN MX 10 mx.miek") | ||||
| 
 | ||||
| In the DNS messages are exchanged, these messages contain resource records | ||||
| (sets). Use pattern for creating a message: | ||||
| 
 | ||||
|      m := new(dns.Msg) | ||||
|      m.SetQuestion("miek.nl.", dns.TypeMX) | ||||
| 
 | ||||
| Or when not certain if the domain name is fully qualified: | ||||
| 
 | ||||
| 	m.SetQuestion(dns.Fqdn("miek.nl"), dns.TypeMX) | ||||
| 
 | ||||
| The message m is now a message with the question section set to ask the MX | ||||
| records for the miek.nl. zone. | ||||
| 
 | ||||
| The following is slightly more verbose, but more flexible: | ||||
| 
 | ||||
|      m1 := new(dns.Msg) | ||||
|      m1.Id = dns.Id() | ||||
|      m1.RecursionDesired = true | ||||
|      m1.Question = make([]dns.Question, 1) | ||||
|      m1.Question[0] = dns.Question{"miek.nl.", dns.TypeMX, dns.ClassINET} | ||||
| 
 | ||||
| After creating a message it can be sent. Basic use pattern for synchronous | ||||
| querying the DNS at a server configured on 127.0.0.1 and port 53: | ||||
| 
 | ||||
|      c := new(dns.Client) | ||||
|      in, rtt, err := c.Exchange(m1, "127.0.0.1:53") | ||||
| 
 | ||||
| Suppressing multiple outstanding queries (with the same question, type and | ||||
| class) is as easy as setting: | ||||
| 
 | ||||
| 	c.SingleInflight = true | ||||
| 
 | ||||
| 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: | ||||
| 
 | ||||
| 	c := new(dns.Client) | ||||
| 	laddr := net.UDPAddr{ | ||||
| 		IP: net.ParseIP("[::1]"), | ||||
| 		Port: 12345, | ||||
| 		Zone: "", | ||||
| 	} | ||||
| 	c.Dialer := &net.Dialer{ | ||||
| 		Timeout: 200 * time.Millisecond, | ||||
| 		LocalAddr: &laddr, | ||||
| 	} | ||||
| 	in, rtt, err := c.Exchange(m1, "8.8.8.8:53") | ||||
| 
 | ||||
| If these "advanced" features are not needed, a simple UDP query can be sent, | ||||
| with: | ||||
| 
 | ||||
| 	in, err := dns.Exchange(m1, "127.0.0.1:53") | ||||
| 
 | ||||
| When this functions returns you will get DNS message. A DNS message consists | ||||
| out of four sections. | ||||
| The question section: in.Question, the answer section: in.Answer, | ||||
| the authority section: in.Ns and the additional section: in.Extra. | ||||
| 
 | ||||
| Each of these sections (except the Question section) contain a []RR. Basic | ||||
| use pattern for accessing the rdata of a TXT RR as the first RR in | ||||
| the Answer section: | ||||
| 
 | ||||
| 	if t, ok := in.Answer[0].(*dns.TXT); ok { | ||||
| 		// do something with t.Txt | ||||
| 	} | ||||
| 
 | ||||
| Domain Name and TXT Character String Representations | ||||
| 
 | ||||
| Both domain names and TXT character strings are converted to presentation form | ||||
| both when unpacked and when converted to strings. | ||||
| 
 | ||||
| For TXT character strings, tabs, carriage returns and line feeds will be | ||||
| converted to \t, \r and \n respectively. Back slashes and quotations marks will | ||||
| be escaped. Bytes below 32 and above 127 will be converted to \DDD form. | ||||
| 
 | ||||
| For domain names, in addition to the above rules brackets, periods, spaces, | ||||
| semicolons and the at symbol are escaped. | ||||
| 
 | ||||
| DNSSEC | ||||
| 
 | ||||
| DNSSEC (DNS Security Extension) adds a layer of security to the DNS. It uses | ||||
| public key cryptography to sign resource records. The public keys are stored in | ||||
| DNSKEY records and the signatures in RRSIG records. | ||||
| 
 | ||||
| Requesting DNSSEC information for a zone is done by adding the DO (DNSSEC OK) | ||||
| bit to a request. | ||||
| 
 | ||||
|      m := new(dns.Msg) | ||||
|      m.SetEdns0(4096, true) | ||||
| 
 | ||||
| Signature generation, signature verification and key generation are all supported. | ||||
| 
 | ||||
| DYNAMIC UPDATES | ||||
| 
 | ||||
| Dynamic updates reuses the DNS message format, but renames three of the | ||||
| sections. Question is Zone, Answer is Prerequisite, Authority is Update, only | ||||
| the Additional is not renamed. See RFC 2136 for the gory details. | ||||
| 
 | ||||
| You can set a rather complex set of rules for the existence of absence of | ||||
| certain resource records or names in a zone to specify if resource records | ||||
| should be added or removed. The table from RFC 2136 supplemented with the Go | ||||
| DNS function shows which functions exist to specify the prerequisites. | ||||
| 
 | ||||
|  3.2.4 - Table Of Metavalues Used In Prerequisite Section | ||||
| 
 | ||||
|   CLASS    TYPE     RDATA    Meaning                    Function | ||||
|   -------------------------------------------------------------- | ||||
|   ANY      ANY      empty    Name is in use             dns.NameUsed | ||||
|   ANY      rrset    empty    RRset exists (value indep) dns.RRsetUsed | ||||
|   NONE     ANY      empty    Name is not in use         dns.NameNotUsed | ||||
|   NONE     rrset    empty    RRset does not exist       dns.RRsetNotUsed | ||||
|   zone     rrset    rr       RRset exists (value dep)   dns.Used | ||||
| 
 | ||||
| The prerequisite section can also be left empty. If you have decided on the | ||||
| prerequisites you can tell what RRs should be added or deleted. The next table | ||||
| shows the options you have and what functions to call. | ||||
| 
 | ||||
|  3.4.2.6 - Table Of Metavalues Used In Update Section | ||||
| 
 | ||||
|   CLASS    TYPE     RDATA    Meaning                     Function | ||||
|   --------------------------------------------------------------- | ||||
|   ANY      ANY      empty    Delete all RRsets from name dns.RemoveName | ||||
|   ANY      rrset    empty    Delete an RRset             dns.RemoveRRset | ||||
|   NONE     rrset    rr       Delete an RR from RRset     dns.Remove | ||||
|   zone     rrset    rr       Add to an RRset             dns.Insert | ||||
| 
 | ||||
| TRANSACTION SIGNATURE | ||||
| 
 | ||||
| An TSIG or transaction signature adds a HMAC TSIG record to each message sent. | ||||
| The supported algorithms include: HmacSHA1, HmacSHA256 and HmacSHA512. | ||||
| 
 | ||||
| Basic use pattern when querying with a TSIG name "axfr." (note that these key names | ||||
| must be fully qualified - as they are domain names) and the base64 secret | ||||
| "so6ZGir4GPAqINNh9U5c3A==": | ||||
| 
 | ||||
| If an incoming message contains a TSIG record it MUST be the last record in | ||||
| the additional section (RFC2845 3.2).  This means that you should make the | ||||
| call to SetTsig last, right before executing the query.  If you make any | ||||
| changes to the RRset after calling SetTsig() the signature will be incorrect. | ||||
| 
 | ||||
| 	c := new(dns.Client) | ||||
| 	c.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="} | ||||
| 	m := new(dns.Msg) | ||||
| 	m.SetQuestion("miek.nl.", dns.TypeMX) | ||||
| 	m.SetTsig("axfr.", dns.HmacSHA256, 300, time.Now().Unix()) | ||||
| 	... | ||||
| 	// When sending the TSIG RR is calculated and filled in before sending | ||||
| 
 | ||||
| When requesting an zone transfer (almost all TSIG usage is when requesting zone | ||||
| transfers), with TSIG, this is the basic use pattern. In this example we | ||||
| request an AXFR for miek.nl. with TSIG key named "axfr." and secret | ||||
| "so6ZGir4GPAqINNh9U5c3A==" and using the server 176.58.119.54: | ||||
| 
 | ||||
| 	t := new(dns.Transfer) | ||||
| 	m := new(dns.Msg) | ||||
| 	t.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="} | ||||
| 	m.SetAxfr("miek.nl.") | ||||
| 	m.SetTsig("axfr.", dns.HmacSHA256, 300, time.Now().Unix()) | ||||
| 	c, err := t.In(m, "176.58.119.54:53") | ||||
| 	for r := range c { ... } | ||||
| 
 | ||||
| You can now read the records from the transfer as they come in. Each envelope | ||||
| is checked with TSIG. If something is not correct an error is returned. | ||||
| 
 | ||||
| A custom TSIG implementation can be used. This requires additional code to | ||||
| perform any session establishment and signature generation/verification. The | ||||
| client must be configured with an implementation of the TsigProvider interface: | ||||
| 
 | ||||
| 	type Provider struct{} | ||||
| 
 | ||||
| 	func (*Provider) Generate(msg []byte, tsig *dns.TSIG) ([]byte, error) { | ||||
| 		// Use tsig.Hdr.Name and tsig.Algorithm in your code to | ||||
| 		// generate the MAC using msg as the payload. | ||||
| 	} | ||||
| 
 | ||||
| 	func (*Provider) Verify(msg []byte, tsig *dns.TSIG) error { | ||||
| 		// Use tsig.Hdr.Name and tsig.Algorithm in your code to verify | ||||
| 		// that msg matches the value in tsig.MAC. | ||||
| 	} | ||||
| 
 | ||||
| 	c := new(dns.Client) | ||||
| 	c.TsigProvider = new(Provider) | ||||
| 	m := new(dns.Msg) | ||||
| 	m.SetQuestion("miek.nl.", dns.TypeMX) | ||||
| 	m.SetTsig(keyname, dns.HmacSHA256, 300, time.Now().Unix()) | ||||
| 	... | ||||
| 	// TSIG RR is calculated by calling your Generate method | ||||
| 
 | ||||
| Basic use pattern validating and replying to a message that has TSIG set. | ||||
| 
 | ||||
| 	server := &dns.Server{Addr: ":53", Net: "udp"} | ||||
| 	server.TsigSecret = map[string]string{"axfr.": "so6ZGir4GPAqINNh9U5c3A=="} | ||||
| 	go server.ListenAndServe() | ||||
| 	dns.HandleFunc(".", handleRequest) | ||||
| 
 | ||||
| 	func handleRequest(w dns.ResponseWriter, r *dns.Msg) { | ||||
| 		m := new(dns.Msg) | ||||
| 		m.SetReply(r) | ||||
| 		if r.IsTsig() != nil { | ||||
| 			if w.TsigStatus() == nil { | ||||
| 				// *Msg r has an TSIG record and it was validated | ||||
| 				m.SetTsig("axfr.", dns.HmacSHA256, 300, time.Now().Unix()) | ||||
| 			} else { | ||||
| 				// *Msg r has an TSIG records and it was not validated | ||||
| 			} | ||||
| 		} | ||||
| 		w.WriteMsg(m) | ||||
| 	} | ||||
| 
 | ||||
| PRIVATE RRS | ||||
| 
 | ||||
| RFC 6895 sets aside a range of type codes for private use. This range is 65,280 | ||||
| - 65,534 (0xFF00 - 0xFFFE). When experimenting with new Resource Records these | ||||
| can be used, before requesting an official type code from IANA. | ||||
| 
 | ||||
| See https://miek.nl/2014/september/21/idn-and-private-rr-in-go-dns/ for more | ||||
| information. | ||||
| 
 | ||||
| EDNS0 | ||||
| 
 | ||||
| EDNS0 is an extension mechanism for the DNS defined in RFC 2671 and updated by | ||||
| RFC 6891. It defines a new RR type, the OPT RR, which is then completely | ||||
| abused. | ||||
| 
 | ||||
| Basic use pattern for creating an (empty) OPT RR: | ||||
| 
 | ||||
| 	o := new(dns.OPT) | ||||
| 	o.Hdr.Name = "." // MUST be the root zone, per definition. | ||||
| 	o.Hdr.Rrtype = dns.TypeOPT | ||||
| 
 | ||||
| The rdata of an OPT RR consists out of a slice of EDNS0 (RFC 6891) interfaces. | ||||
| Currently only a few have been standardized: EDNS0_NSID (RFC 5001) and | ||||
| EDNS0_SUBNET (RFC 7871). Note that these options may be combined in an OPT RR. | ||||
| Basic use pattern for a server to check if (and which) options are set: | ||||
| 
 | ||||
| 	// o is a dns.OPT | ||||
| 	for _, s := range o.Option { | ||||
| 		switch e := s.(type) { | ||||
| 		case *dns.EDNS0_NSID: | ||||
| 			// do stuff with e.Nsid | ||||
| 		case *dns.EDNS0_SUBNET: | ||||
| 			// access e.Family, e.Address, etc. | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| SIG(0) | ||||
| 
 | ||||
| From RFC 2931: | ||||
| 
 | ||||
|     SIG(0) provides protection for DNS transactions and requests .... | ||||
|     ... protection for glue records, DNS requests, protection for message headers | ||||
|     on requests and responses, and protection of the overall integrity of a response. | ||||
| 
 | ||||
| It works like TSIG, except that SIG(0) uses public key cryptography, instead of | ||||
| the shared secret approach in TSIG. Supported algorithms: ECDSAP256SHA256, | ||||
| ECDSAP384SHA384, RSASHA1, RSASHA256 and RSASHA512. | ||||
| 
 | ||||
| Signing subsequent messages in multi-message sessions is not implemented. | ||||
| */ | ||||
| package dns | ||||
							
								
								
									
										37
									
								
								vendor/github.com/miekg/dns/duplicate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/github.com/miekg/dns/duplicate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| package dns | ||||
| 
 | ||||
| //go:generate go run duplicate_generate.go | ||||
| 
 | ||||
| // IsDuplicate checks of r1 and r2 are duplicates of each other, excluding the TTL. | ||||
| // So this means the header data is equal *and* the RDATA is the same. Returns true | ||||
| // if so, otherwise false. It's a protocol violation to have identical RRs in a message. | ||||
| func IsDuplicate(r1, r2 RR) bool { | ||||
| 	// Check whether the record header is identical. | ||||
| 	if !r1.Header().isDuplicate(r2.Header()) { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	// Check whether the RDATA is identical. | ||||
| 	return r1.isDuplicate(r2) | ||||
| } | ||||
| 
 | ||||
| func (r1 *RR_Header) isDuplicate(_r2 RR) bool { | ||||
| 	r2, ok := _r2.(*RR_Header) | ||||
| 	if !ok { | ||||
| 		return false | ||||
| 	} | ||||
| 	if r1.Class != r2.Class { | ||||
| 		return false | ||||
| 	} | ||||
| 	if r1.Rrtype != r2.Rrtype { | ||||
| 		return false | ||||
| 	} | ||||
| 	if !isDuplicateName(r1.Name, r2.Name) { | ||||
| 		return false | ||||
| 	} | ||||
| 	// ignore TTL | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // isDuplicateName checks if the domain names s1 and s2 are equal. | ||||
| func isDuplicateName(s1, s2 string) bool { return equal(s1, s2) } | ||||
							
								
								
									
										851
									
								
								vendor/github.com/miekg/dns/edns.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										851
									
								
								vendor/github.com/miekg/dns/edns.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,851 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/binary" | ||||
| 	"encoding/hex" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| // EDNS0 Option codes. | ||||
| 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 (See RFC 5001) | ||||
| 	EDNS0ESU          = 0x4     // ENUM Source-URI draft: https://datatracker.ietf.org/doc/html/draft-kaplan-enum-source-uri-00 | ||||
| 	EDNS0DAU          = 0x5     // DNSSEC Algorithm Understood | ||||
| 	EDNS0DHU          = 0x6     // DS Hash Understood | ||||
| 	EDNS0N3U          = 0x7     // NSEC3 Hash Understood | ||||
| 	EDNS0SUBNET       = 0x8     // client-subnet (See RFC 7871) | ||||
| 	EDNS0EXPIRE       = 0x9     // EDNS0 expire | ||||
| 	EDNS0COOKIE       = 0xa     // EDNS0 Cookie | ||||
| 	EDNS0TCPKEEPALIVE = 0xb     // EDNS0 tcp keep alive (See RFC 7828) | ||||
| 	EDNS0PADDING      = 0xc     // EDNS0 padding (See RFC 7830) | ||||
| 	EDNS0EDE          = 0xf     // EDNS0 extended DNS errors (See RFC 8914) | ||||
| 	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 | ||||
| ) | ||||
| 
 | ||||
| // makeDataOpt is used to unpack the EDNS0 option(s) from a message. | ||||
| func makeDataOpt(code uint16) EDNS0 { | ||||
| 	// All the EDNS0.* constants above need to be in this switch. | ||||
| 	switch code { | ||||
| 	case EDNS0LLQ: | ||||
| 		return new(EDNS0_LLQ) | ||||
| 	case EDNS0UL: | ||||
| 		return new(EDNS0_UL) | ||||
| 	case EDNS0NSID: | ||||
| 		return new(EDNS0_NSID) | ||||
| 	case EDNS0DAU: | ||||
| 		return new(EDNS0_DAU) | ||||
| 	case EDNS0DHU: | ||||
| 		return new(EDNS0_DHU) | ||||
| 	case EDNS0N3U: | ||||
| 		return new(EDNS0_N3U) | ||||
| 	case EDNS0SUBNET: | ||||
| 		return new(EDNS0_SUBNET) | ||||
| 	case EDNS0EXPIRE: | ||||
| 		return new(EDNS0_EXPIRE) | ||||
| 	case EDNS0COOKIE: | ||||
| 		return new(EDNS0_COOKIE) | ||||
| 	case EDNS0TCPKEEPALIVE: | ||||
| 		return new(EDNS0_TCP_KEEPALIVE) | ||||
| 	case EDNS0PADDING: | ||||
| 		return new(EDNS0_PADDING) | ||||
| 	case EDNS0EDE: | ||||
| 		return new(EDNS0_EDE) | ||||
| 	case EDNS0ESU: | ||||
| 		return &EDNS0_ESU{Code: EDNS0ESU} | ||||
| 	default: | ||||
| 		e := new(EDNS0_LOCAL) | ||||
| 		e.Code = code | ||||
| 		return e | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // OPT is the EDNS0 RR appended to messages to convey extra (meta) information. | ||||
| // See RFC 6891. | ||||
| type OPT struct { | ||||
| 	Hdr    RR_Header | ||||
| 	Option []EDNS0 `dns:"opt"` | ||||
| } | ||||
| 
 | ||||
| func (rr *OPT) String() string { | ||||
| 	s := "\n;; OPT PSEUDOSECTION:\n; EDNS: version " + strconv.Itoa(int(rr.Version())) + "; " | ||||
| 	if rr.Do() { | ||||
| 		s += "flags: do; " | ||||
| 	} else { | ||||
| 		s += "flags: ; " | ||||
| 	} | ||||
| 	s += "udp: " + strconv.Itoa(int(rr.UDPSize())) | ||||
| 
 | ||||
| 	for _, o := range rr.Option { | ||||
| 		switch o.(type) { | ||||
| 		case *EDNS0_NSID: | ||||
| 			s += "\n; NSID: " + o.String() | ||||
| 			h, e := o.pack() | ||||
| 			var r string | ||||
| 			if e == nil { | ||||
| 				for _, c := range h { | ||||
| 					r += "(" + string(c) + ")" | ||||
| 				} | ||||
| 				s += "  " + r | ||||
| 			} | ||||
| 		case *EDNS0_SUBNET: | ||||
| 			s += "\n; SUBNET: " + o.String() | ||||
| 		case *EDNS0_COOKIE: | ||||
| 			s += "\n; COOKIE: " + o.String() | ||||
| 		case *EDNS0_TCP_KEEPALIVE: | ||||
| 			s += "\n; KEEPALIVE: " + o.String() | ||||
| 		case *EDNS0_UL: | ||||
| 			s += "\n; UPDATE LEASE: " + o.String() | ||||
| 		case *EDNS0_LLQ: | ||||
| 			s += "\n; LONG LIVED QUERIES: " + o.String() | ||||
| 		case *EDNS0_DAU: | ||||
| 			s += "\n; DNSSEC ALGORITHM UNDERSTOOD: " + o.String() | ||||
| 		case *EDNS0_DHU: | ||||
| 			s += "\n; DS HASH UNDERSTOOD: " + o.String() | ||||
| 		case *EDNS0_N3U: | ||||
| 			s += "\n; NSEC3 HASH UNDERSTOOD: " + o.String() | ||||
| 		case *EDNS0_LOCAL: | ||||
| 			s += "\n; LOCAL OPT: " + o.String() | ||||
| 		case *EDNS0_PADDING: | ||||
| 			s += "\n; PADDING: " + o.String() | ||||
| 		case *EDNS0_EDE: | ||||
| 			s += "\n; EDE: " + o.String() | ||||
| 		case *EDNS0_ESU: | ||||
| 			s += "\n; ESU: " + o.String() | ||||
| 		} | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
| 
 | ||||
| func (rr *OPT) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	for _, o := range rr.Option { | ||||
| 		l += 4 // Account for 2-byte option code and 2-byte option length. | ||||
| 		lo, _ := o.pack() | ||||
| 		l += len(lo) | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| 
 | ||||
| func (*OPT) parse(c *zlexer, origin string) *ParseError { | ||||
| 	return &ParseError{err: "OPT records do not have a presentation format"} | ||||
| } | ||||
| 
 | ||||
| func (rr *OPT) isDuplicate(r2 RR) bool { return false } | ||||
| 
 | ||||
| // return the old value -> delete SetVersion? | ||||
| 
 | ||||
| // Version returns the EDNS version used. Only zero is defined. | ||||
| func (rr *OPT) Version() uint8 { | ||||
| 	return uint8(rr.Hdr.Ttl & 0x00FF0000 >> 16) | ||||
| } | ||||
| 
 | ||||
| // SetVersion sets the version of EDNS. This is usually zero. | ||||
| func (rr *OPT) SetVersion(v uint8) { | ||||
| 	rr.Hdr.Ttl = rr.Hdr.Ttl&0xFF00FFFF | uint32(v)<<16 | ||||
| } | ||||
| 
 | ||||
| // ExtendedRcode returns the EDNS extended RCODE field (the upper 8 bits of the TTL). | ||||
| func (rr *OPT) ExtendedRcode() int { | ||||
| 	return int(rr.Hdr.Ttl&0xFF000000>>24) << 4 | ||||
| } | ||||
| 
 | ||||
| // SetExtendedRcode sets the EDNS extended RCODE field. | ||||
| // | ||||
| // If the RCODE is not an extended RCODE, will reset the extended RCODE field to 0. | ||||
| func (rr *OPT) SetExtendedRcode(v uint16) { | ||||
| 	rr.Hdr.Ttl = rr.Hdr.Ttl&0x00FFFFFF | uint32(v>>4)<<24 | ||||
| } | ||||
| 
 | ||||
| // UDPSize returns the UDP buffer size. | ||||
| func (rr *OPT) UDPSize() uint16 { | ||||
| 	return rr.Hdr.Class | ||||
| } | ||||
| 
 | ||||
| // SetUDPSize sets the UDP buffer size. | ||||
| func (rr *OPT) SetUDPSize(size uint16) { | ||||
| 	rr.Hdr.Class = size | ||||
| } | ||||
| 
 | ||||
| // Do returns the value of the DO (DNSSEC OK) bit. | ||||
| func (rr *OPT) Do() bool { | ||||
| 	return rr.Hdr.Ttl&_DO == _DO | ||||
| } | ||||
| 
 | ||||
| // SetDo sets the DO (DNSSEC OK) bit. | ||||
| // If we pass an argument, set the DO bit to that value. | ||||
| // It is possible to pass 2 or more arguments. Any arguments after the 1st is silently ignored. | ||||
| func (rr *OPT) SetDo(do ...bool) { | ||||
| 	if len(do) == 1 { | ||||
| 		if do[0] { | ||||
| 			rr.Hdr.Ttl |= _DO | ||||
| 		} else { | ||||
| 			rr.Hdr.Ttl &^= _DO | ||||
| 		} | ||||
| 	} else { | ||||
| 		rr.Hdr.Ttl |= _DO | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Z returns the Z part of the OPT RR as a uint16 with only the 15 least significant bits used. | ||||
| func (rr *OPT) Z() uint16 { | ||||
| 	return uint16(rr.Hdr.Ttl & 0x7FFF) | ||||
| } | ||||
| 
 | ||||
| // SetZ sets the Z part of the OPT RR, note only the 15 least significant bits of z are used. | ||||
| func (rr *OPT) SetZ(z uint16) { | ||||
| 	rr.Hdr.Ttl = rr.Hdr.Ttl&^0x7FFF | uint32(z&0x7FFF) | ||||
| } | ||||
| 
 | ||||
| // EDNS0 defines an EDNS0 Option. An OPT RR can have multiple options appended to it. | ||||
| type EDNS0 interface { | ||||
| 	// Option returns the option code for the option. | ||||
| 	Option() uint16 | ||||
| 	// pack returns the bytes of the option data. | ||||
| 	pack() ([]byte, error) | ||||
| 	// unpack sets the data as found in the buffer. Is also sets | ||||
| 	// the length of the slice as the length of the option data. | ||||
| 	unpack([]byte) error | ||||
| 	// String returns the string representation of the option. | ||||
| 	String() string | ||||
| 	// copy returns a deep-copy of the option. | ||||
| 	copy() EDNS0 | ||||
| } | ||||
| 
 | ||||
| // EDNS0_NSID option is used to retrieve a nameserver | ||||
| // identifier. When sending a request Nsid must be set to the empty string | ||||
| // The identifier is an opaque string encoded as hex. | ||||
| // Basic use pattern for creating an nsid option: | ||||
| // | ||||
| //	o := new(dns.OPT) | ||||
| //	o.Hdr.Name = "." | ||||
| //	o.Hdr.Rrtype = dns.TypeOPT | ||||
| //	e := new(dns.EDNS0_NSID) | ||||
| //	e.Code = dns.EDNS0NSID | ||||
| //	e.Nsid = "AA" | ||||
| //	o.Option = append(o.Option, e) | ||||
| type EDNS0_NSID struct { | ||||
| 	Code uint16 // Always EDNS0NSID | ||||
| 	Nsid string // This string needs to be hex encoded | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_NSID) pack() ([]byte, error) { | ||||
| 	h, err := hex.DecodeString(e.Nsid) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return h, nil | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_NSID) Option() uint16        { return EDNS0NSID } // Option returns the option code. | ||||
| func (e *EDNS0_NSID) unpack(b []byte) error { e.Nsid = hex.EncodeToString(b); return nil } | ||||
| func (e *EDNS0_NSID) String() string        { return e.Nsid } | ||||
| func (e *EDNS0_NSID) copy() EDNS0           { return &EDNS0_NSID{e.Code, e.Nsid} } | ||||
| 
 | ||||
| // EDNS0_SUBNET is the subnet option that is used to give the remote nameserver | ||||
| // 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: | ||||
| // | ||||
| //	o := new(dns.OPT) | ||||
| //	o.Hdr.Name = "." | ||||
| //	o.Hdr.Rrtype = dns.TypeOPT | ||||
| //	e := new(dns.EDNS0_SUBNET) | ||||
| //	e.Code = dns.EDNS0SUBNET | ||||
| //	e.Family = 1	// 1 for IPv4 source address, 2 for IPv6 | ||||
| //	e.SourceNetmask = 32	// 32 for IPV4, 128 for IPv6 | ||||
| //	e.SourceScope = 0 | ||||
| //	e.Address = net.ParseIP("127.0.0.1").To4()	// for IPv4 | ||||
| //	// e.Address = net.ParseIP("2001:7b8:32a::2")	// for IPV6 | ||||
| //	o.Option = append(o.Option, e) | ||||
| // | ||||
| // 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 | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_SUBNET) Option() uint16 { return EDNS0SUBNET } | ||||
| 
 | ||||
| func (e *EDNS0_SUBNET) pack() ([]byte, error) { | ||||
| 	b := make([]byte, 4) | ||||
| 	binary.BigEndian.PutUint16(b[0:], e.Family) | ||||
| 	b[2] = e.SourceNetmask | ||||
| 	b[3] = e.SourceScope | ||||
| 	switch e.Family { | ||||
| 	case 0: | ||||
| 		// "dig" sets AddressFamily to 0 if SourceNetmask is also 0 | ||||
| 		// We might don't need to complain either | ||||
| 		if e.SourceNetmask != 0 { | ||||
| 			return nil, errors.New("dns: bad address family") | ||||
| 		} | ||||
| 	case 1: | ||||
| 		if e.SourceNetmask > net.IPv4len*8 { | ||||
| 			return nil, errors.New("dns: bad netmask") | ||||
| 		} | ||||
| 		if len(e.Address.To4()) != net.IPv4len { | ||||
| 			return nil, errors.New("dns: bad address") | ||||
| 		} | ||||
| 		ip := e.Address.To4().Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv4len*8)) | ||||
| 		needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up | ||||
| 		b = append(b, ip[:needLength]...) | ||||
| 	case 2: | ||||
| 		if e.SourceNetmask > net.IPv6len*8 { | ||||
| 			return nil, errors.New("dns: bad netmask") | ||||
| 		} | ||||
| 		if len(e.Address) != net.IPv6len { | ||||
| 			return nil, errors.New("dns: bad address") | ||||
| 		} | ||||
| 		ip := e.Address.Mask(net.CIDRMask(int(e.SourceNetmask), net.IPv6len*8)) | ||||
| 		needLength := (e.SourceNetmask + 8 - 1) / 8 // division rounding up | ||||
| 		b = append(b, ip[:needLength]...) | ||||
| 	default: | ||||
| 		return nil, errors.New("dns: bad address family") | ||||
| 	} | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_SUBNET) unpack(b []byte) error { | ||||
| 	if len(b) < 4 { | ||||
| 		return ErrBuf | ||||
| 	} | ||||
| 	e.Family = binary.BigEndian.Uint16(b) | ||||
| 	e.SourceNetmask = b[2] | ||||
| 	e.SourceScope = b[3] | ||||
| 	switch e.Family { | ||||
| 	case 0: | ||||
| 		// "dig" sets AddressFamily to 0 if SourceNetmask is also 0 | ||||
| 		// It's okay to accept such a packet | ||||
| 		if e.SourceNetmask != 0 { | ||||
| 			return errors.New("dns: bad address family") | ||||
| 		} | ||||
| 		e.Address = net.IPv4(0, 0, 0, 0) | ||||
| 	case 1: | ||||
| 		if e.SourceNetmask > net.IPv4len*8 || e.SourceScope > net.IPv4len*8 { | ||||
| 			return errors.New("dns: bad netmask") | ||||
| 		} | ||||
| 		addr := make(net.IP, net.IPv4len) | ||||
| 		copy(addr, b[4:]) | ||||
| 		e.Address = addr.To16() | ||||
| 	case 2: | ||||
| 		if e.SourceNetmask > net.IPv6len*8 || e.SourceScope > net.IPv6len*8 { | ||||
| 			return errors.New("dns: bad netmask") | ||||
| 		} | ||||
| 		addr := make(net.IP, net.IPv6len) | ||||
| 		copy(addr, b[4:]) | ||||
| 		e.Address = addr | ||||
| 	default: | ||||
| 		return errors.New("dns: bad address family") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_SUBNET) String() (s string) { | ||||
| 	if e.Address == nil { | ||||
| 		s = "<nil>" | ||||
| 	} else if e.Address.To4() != nil { | ||||
| 		s = e.Address.String() | ||||
| 	} else { | ||||
| 		s = "[" + e.Address.String() + "]" | ||||
| 	} | ||||
| 	s += "/" + strconv.Itoa(int(e.SourceNetmask)) + "/" + strconv.Itoa(int(e.SourceScope)) | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_SUBNET) copy() EDNS0 { | ||||
| 	return &EDNS0_SUBNET{ | ||||
| 		e.Code, | ||||
| 		e.Family, | ||||
| 		e.SourceNetmask, | ||||
| 		e.SourceScope, | ||||
| 		e.Address, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // The EDNS0_COOKIE option is used to add a DNS Cookie to a message. | ||||
| // | ||||
| //	o := new(dns.OPT) | ||||
| //	o.Hdr.Name = "." | ||||
| //	o.Hdr.Rrtype = dns.TypeOPT | ||||
| //	e := new(dns.EDNS0_COOKIE) | ||||
| //	e.Code = dns.EDNS0COOKIE | ||||
| //	e.Cookie = "24a5ac.." | ||||
| //	o.Option = append(o.Option, e) | ||||
| // | ||||
| // The Cookie field consists out of a client cookie (RFC 7873 Section 4), that is | ||||
| // always 8 bytes. It may then optionally be followed by the server cookie. The server | ||||
| // cookie is of variable length, 8 to a maximum of 32 bytes. In other words: | ||||
| // | ||||
| //	cCookie := o.Cookie[:16] | ||||
| //	sCookie := o.Cookie[16:] | ||||
| // | ||||
| // There is no guarantee that the Cookie string has a specific length. | ||||
| type EDNS0_COOKIE struct { | ||||
| 	Code   uint16 // Always EDNS0COOKIE | ||||
| 	Cookie string // Hex-encoded cookie data | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_COOKIE) pack() ([]byte, error) { | ||||
| 	h, err := hex.DecodeString(e.Cookie) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return h, nil | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_COOKIE) Option() uint16        { return EDNS0COOKIE } | ||||
| func (e *EDNS0_COOKIE) unpack(b []byte) error { e.Cookie = hex.EncodeToString(b); return nil } | ||||
| func (e *EDNS0_COOKIE) String() string        { return e.Cookie } | ||||
| func (e *EDNS0_COOKIE) copy() EDNS0           { return &EDNS0_COOKIE{e.Code, e.Cookie} } | ||||
| 
 | ||||
| // The EDNS0_UL (Update Lease) (draft RFC) option is used to tell the server to set | ||||
| // an expiration on an update RR. This is helpful for clients that cannot clean | ||||
| // up after themselves. This is a draft RFC and more information can be found at | ||||
| // https://tools.ietf.org/html/draft-sekar-dns-ul-02 | ||||
| // | ||||
| //	o := new(dns.OPT) | ||||
| //	o.Hdr.Name = "." | ||||
| //	o.Hdr.Rrtype = dns.TypeOPT | ||||
| //	e := new(dns.EDNS0_UL) | ||||
| //	e.Code = dns.EDNS0UL | ||||
| //	e.Lease = 120 // in seconds | ||||
| //	o.Option = append(o.Option, e) | ||||
| type EDNS0_UL struct { | ||||
| 	Code     uint16 // Always EDNS0UL | ||||
| 	Lease    uint32 | ||||
| 	KeyLease uint32 | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_UL) Option() uint16 { return EDNS0UL } | ||||
| func (e *EDNS0_UL) String() string { return fmt.Sprintf("%d %d", e.Lease, e.KeyLease) } | ||||
| func (e *EDNS0_UL) copy() EDNS0    { return &EDNS0_UL{e.Code, e.Lease, e.KeyLease} } | ||||
| 
 | ||||
| // Copied: http://golang.org/src/pkg/net/dnsmsg.go | ||||
| func (e *EDNS0_UL) pack() ([]byte, error) { | ||||
| 	var b []byte | ||||
| 	if e.KeyLease == 0 { | ||||
| 		b = make([]byte, 4) | ||||
| 	} else { | ||||
| 		b = make([]byte, 8) | ||||
| 		binary.BigEndian.PutUint32(b[4:], e.KeyLease) | ||||
| 	} | ||||
| 	binary.BigEndian.PutUint32(b, e.Lease) | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_UL) unpack(b []byte) error { | ||||
| 	switch len(b) { | ||||
| 	case 4: | ||||
| 		e.KeyLease = 0 | ||||
| 	case 8: | ||||
| 		e.KeyLease = binary.BigEndian.Uint32(b[4:]) | ||||
| 	default: | ||||
| 		return ErrBuf | ||||
| 	} | ||||
| 	e.Lease = binary.BigEndian.Uint32(b) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // EDNS0_LLQ stands for Long Lived Queries: http://tools.ietf.org/html/draft-sekar-dns-llq-01 | ||||
| // Implemented for completeness, as the EDNS0 type code is assigned. | ||||
| type EDNS0_LLQ struct { | ||||
| 	Code      uint16 // Always EDNS0LLQ | ||||
| 	Version   uint16 | ||||
| 	Opcode    uint16 | ||||
| 	Error     uint16 | ||||
| 	Id        uint64 | ||||
| 	LeaseLife uint32 | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_LLQ) Option() uint16 { return EDNS0LLQ } | ||||
| 
 | ||||
| func (e *EDNS0_LLQ) pack() ([]byte, error) { | ||||
| 	b := make([]byte, 18) | ||||
| 	binary.BigEndian.PutUint16(b[0:], e.Version) | ||||
| 	binary.BigEndian.PutUint16(b[2:], e.Opcode) | ||||
| 	binary.BigEndian.PutUint16(b[4:], e.Error) | ||||
| 	binary.BigEndian.PutUint64(b[6:], e.Id) | ||||
| 	binary.BigEndian.PutUint32(b[14:], e.LeaseLife) | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_LLQ) unpack(b []byte) error { | ||||
| 	if len(b) < 18 { | ||||
| 		return ErrBuf | ||||
| 	} | ||||
| 	e.Version = binary.BigEndian.Uint16(b[0:]) | ||||
| 	e.Opcode = binary.BigEndian.Uint16(b[2:]) | ||||
| 	e.Error = binary.BigEndian.Uint16(b[4:]) | ||||
| 	e.Id = binary.BigEndian.Uint64(b[6:]) | ||||
| 	e.LeaseLife = binary.BigEndian.Uint32(b[14:]) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_LLQ) String() string { | ||||
| 	s := strconv.FormatUint(uint64(e.Version), 10) + " " + strconv.FormatUint(uint64(e.Opcode), 10) + | ||||
| 		" " + strconv.FormatUint(uint64(e.Error), 10) + " " + strconv.FormatUint(e.Id, 10) + | ||||
| 		" " + strconv.FormatUint(uint64(e.LeaseLife), 10) | ||||
| 	return s | ||||
| } | ||||
| func (e *EDNS0_LLQ) copy() EDNS0 { | ||||
| 	return &EDNS0_LLQ{e.Code, e.Version, e.Opcode, e.Error, e.Id, e.LeaseLife} | ||||
| } | ||||
| 
 | ||||
| // EDNS0_DAU implements the EDNS0 "DNSSEC Algorithm Understood" option. See RFC 6975. | ||||
| type EDNS0_DAU struct { | ||||
| 	Code    uint16 // Always EDNS0DAU | ||||
| 	AlgCode []uint8 | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_DAU) Option() uint16        { return EDNS0DAU } | ||||
| func (e *EDNS0_DAU) pack() ([]byte, error) { return e.AlgCode, nil } | ||||
| func (e *EDNS0_DAU) unpack(b []byte) error { e.AlgCode = b; return nil } | ||||
| 
 | ||||
| func (e *EDNS0_DAU) String() string { | ||||
| 	s := "" | ||||
| 	for _, alg := range e.AlgCode { | ||||
| 		if a, ok := AlgorithmToString[alg]; ok { | ||||
| 			s += " " + a | ||||
| 		} else { | ||||
| 			s += " " + strconv.Itoa(int(alg)) | ||||
| 		} | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
| func (e *EDNS0_DAU) copy() EDNS0 { return &EDNS0_DAU{e.Code, e.AlgCode} } | ||||
| 
 | ||||
| // EDNS0_DHU implements the EDNS0 "DS Hash Understood" option. See RFC 6975. | ||||
| type EDNS0_DHU struct { | ||||
| 	Code    uint16 // Always EDNS0DHU | ||||
| 	AlgCode []uint8 | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_DHU) Option() uint16        { return EDNS0DHU } | ||||
| func (e *EDNS0_DHU) pack() ([]byte, error) { return e.AlgCode, nil } | ||||
| func (e *EDNS0_DHU) unpack(b []byte) error { e.AlgCode = b; return nil } | ||||
| 
 | ||||
| func (e *EDNS0_DHU) String() string { | ||||
| 	s := "" | ||||
| 	for _, alg := range e.AlgCode { | ||||
| 		if a, ok := HashToString[alg]; ok { | ||||
| 			s += " " + a | ||||
| 		} else { | ||||
| 			s += " " + strconv.Itoa(int(alg)) | ||||
| 		} | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
| func (e *EDNS0_DHU) copy() EDNS0 { return &EDNS0_DHU{e.Code, e.AlgCode} } | ||||
| 
 | ||||
| // EDNS0_N3U implements the EDNS0 "NSEC3 Hash Understood" option. See RFC 6975. | ||||
| type EDNS0_N3U struct { | ||||
| 	Code    uint16 // Always EDNS0N3U | ||||
| 	AlgCode []uint8 | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_N3U) Option() uint16        { return EDNS0N3U } | ||||
| func (e *EDNS0_N3U) pack() ([]byte, error) { return e.AlgCode, nil } | ||||
| func (e *EDNS0_N3U) unpack(b []byte) error { e.AlgCode = b; return nil } | ||||
| 
 | ||||
| func (e *EDNS0_N3U) String() string { | ||||
| 	// Re-use the hash map | ||||
| 	s := "" | ||||
| 	for _, alg := range e.AlgCode { | ||||
| 		if a, ok := HashToString[alg]; ok { | ||||
| 			s += " " + a | ||||
| 		} else { | ||||
| 			s += " " + strconv.Itoa(int(alg)) | ||||
| 		} | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
| func (e *EDNS0_N3U) copy() EDNS0 { return &EDNS0_N3U{e.Code, e.AlgCode} } | ||||
| 
 | ||||
| // EDNS0_EXPIRE implements the EDNS0 option as described in RFC 7314. | ||||
| type EDNS0_EXPIRE struct { | ||||
| 	Code   uint16 // Always EDNS0EXPIRE | ||||
| 	Expire uint32 | ||||
| 	Empty  bool // Empty is used to signal an empty Expire option in a backwards compatible way, it's not used on the wire. | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_EXPIRE) Option() uint16 { return EDNS0EXPIRE } | ||||
| func (e *EDNS0_EXPIRE) copy() EDNS0    { return &EDNS0_EXPIRE{e.Code, e.Expire, e.Empty} } | ||||
| 
 | ||||
| func (e *EDNS0_EXPIRE) pack() ([]byte, error) { | ||||
| 	if e.Empty { | ||||
| 		return []byte{}, nil | ||||
| 	} | ||||
| 	b := make([]byte, 4) | ||||
| 	binary.BigEndian.PutUint32(b, e.Expire) | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_EXPIRE) unpack(b []byte) error { | ||||
| 	if len(b) == 0 { | ||||
| 		// zero-length EXPIRE query, see RFC 7314 Section 2 | ||||
| 		e.Empty = true | ||||
| 		return nil | ||||
| 	} | ||||
| 	if len(b) < 4 { | ||||
| 		return ErrBuf | ||||
| 	} | ||||
| 	e.Expire = binary.BigEndian.Uint32(b) | ||||
| 	e.Empty = false | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_EXPIRE) String() (s string) { | ||||
| 	if e.Empty { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return strconv.FormatUint(uint64(e.Expire), 10) | ||||
| } | ||||
| 
 | ||||
| // The EDNS0_LOCAL option is used for local/experimental purposes. The option | ||||
| // code is recommended to be within the range [EDNS0LOCALSTART, EDNS0LOCALEND] | ||||
| // (RFC6891), although any unassigned code can actually be used.  The content of | ||||
| // the option is made available in Data, unaltered. | ||||
| // Basic use pattern for creating a local option: | ||||
| // | ||||
| //	o := new(dns.OPT) | ||||
| //	o.Hdr.Name = "." | ||||
| //	o.Hdr.Rrtype = dns.TypeOPT | ||||
| //	e := new(dns.EDNS0_LOCAL) | ||||
| //	e.Code = dns.EDNS0LOCALSTART | ||||
| //	e.Data = []byte{72, 82, 74} | ||||
| //	o.Option = append(o.Option, e) | ||||
| type EDNS0_LOCAL struct { | ||||
| 	Code uint16 | ||||
| 	Data []byte | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_LOCAL) Option() uint16 { return e.Code } | ||||
| func (e *EDNS0_LOCAL) String() string { | ||||
| 	return strconv.FormatInt(int64(e.Code), 10) + ":0x" + hex.EncodeToString(e.Data) | ||||
| } | ||||
| func (e *EDNS0_LOCAL) copy() EDNS0 { | ||||
| 	b := make([]byte, len(e.Data)) | ||||
| 	copy(b, e.Data) | ||||
| 	return &EDNS0_LOCAL{e.Code, b} | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_LOCAL) pack() ([]byte, error) { | ||||
| 	b := make([]byte, len(e.Data)) | ||||
| 	copied := copy(b, e.Data) | ||||
| 	if copied != len(e.Data) { | ||||
| 		return nil, ErrBuf | ||||
| 	} | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_LOCAL) unpack(b []byte) error { | ||||
| 	e.Data = make([]byte, len(b)) | ||||
| 	copied := copy(e.Data, b) | ||||
| 	if copied != len(b) { | ||||
| 		return ErrBuf | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // EDNS0_TCP_KEEPALIVE is an EDNS0 option that instructs the server to keep | ||||
| // the TCP connection alive. See RFC 7828. | ||||
| type EDNS0_TCP_KEEPALIVE struct { | ||||
| 	Code uint16 // Always EDNSTCPKEEPALIVE | ||||
| 
 | ||||
| 	// Timeout is an idle timeout value for the TCP connection, specified in | ||||
| 	// units of 100 milliseconds, encoded in network byte order. If set to 0, | ||||
| 	// pack will return a nil slice. | ||||
| 	Timeout uint16 | ||||
| 
 | ||||
| 	// Length is the option's length. | ||||
| 	// Deprecated: this field is deprecated and is always equal to 0. | ||||
| 	Length uint16 | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_TCP_KEEPALIVE) Option() uint16 { return EDNS0TCPKEEPALIVE } | ||||
| 
 | ||||
| func (e *EDNS0_TCP_KEEPALIVE) pack() ([]byte, error) { | ||||
| 	if e.Timeout > 0 { | ||||
| 		b := make([]byte, 2) | ||||
| 		binary.BigEndian.PutUint16(b, e.Timeout) | ||||
| 		return b, nil | ||||
| 	} | ||||
| 	return nil, nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_TCP_KEEPALIVE) unpack(b []byte) error { | ||||
| 	switch len(b) { | ||||
| 	case 0: | ||||
| 	case 2: | ||||
| 		e.Timeout = binary.BigEndian.Uint16(b) | ||||
| 	default: | ||||
| 		return fmt.Errorf("dns: length mismatch, want 0/2 but got %d", len(b)) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_TCP_KEEPALIVE) String() string { | ||||
| 	s := "use tcp keep-alive" | ||||
| 	if e.Timeout == 0 { | ||||
| 		s += ", timeout omitted" | ||||
| 	} else { | ||||
| 		s += fmt.Sprintf(", timeout %dms", e.Timeout*100) | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_TCP_KEEPALIVE) copy() EDNS0 { return &EDNS0_TCP_KEEPALIVE{e.Code, e.Timeout, e.Length} } | ||||
| 
 | ||||
| // EDNS0_PADDING option is used to add padding to a request/response. The default | ||||
| // value of padding SHOULD be 0x0 but other values MAY be used, for instance if | ||||
| // compression is applied before encryption which may break signatures. | ||||
| type EDNS0_PADDING struct { | ||||
| 	Padding []byte | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_PADDING) Option() uint16        { return EDNS0PADDING } | ||||
| func (e *EDNS0_PADDING) pack() ([]byte, error) { return e.Padding, nil } | ||||
| func (e *EDNS0_PADDING) unpack(b []byte) error { e.Padding = b; return nil } | ||||
| func (e *EDNS0_PADDING) String() string        { return fmt.Sprintf("%0X", e.Padding) } | ||||
| func (e *EDNS0_PADDING) copy() EDNS0 { | ||||
| 	b := make([]byte, len(e.Padding)) | ||||
| 	copy(b, e.Padding) | ||||
| 	return &EDNS0_PADDING{b} | ||||
| } | ||||
| 
 | ||||
| // Extended DNS Error Codes (RFC 8914). | ||||
| const ( | ||||
| 	ExtendedErrorCodeOther uint16 = iota | ||||
| 	ExtendedErrorCodeUnsupportedDNSKEYAlgorithm | ||||
| 	ExtendedErrorCodeUnsupportedDSDigestType | ||||
| 	ExtendedErrorCodeStaleAnswer | ||||
| 	ExtendedErrorCodeForgedAnswer | ||||
| 	ExtendedErrorCodeDNSSECIndeterminate | ||||
| 	ExtendedErrorCodeDNSBogus | ||||
| 	ExtendedErrorCodeSignatureExpired | ||||
| 	ExtendedErrorCodeSignatureNotYetValid | ||||
| 	ExtendedErrorCodeDNSKEYMissing | ||||
| 	ExtendedErrorCodeRRSIGsMissing | ||||
| 	ExtendedErrorCodeNoZoneKeyBitSet | ||||
| 	ExtendedErrorCodeNSECMissing | ||||
| 	ExtendedErrorCodeCachedError | ||||
| 	ExtendedErrorCodeNotReady | ||||
| 	ExtendedErrorCodeBlocked | ||||
| 	ExtendedErrorCodeCensored | ||||
| 	ExtendedErrorCodeFiltered | ||||
| 	ExtendedErrorCodeProhibited | ||||
| 	ExtendedErrorCodeStaleNXDOMAINAnswer | ||||
| 	ExtendedErrorCodeNotAuthoritative | ||||
| 	ExtendedErrorCodeNotSupported | ||||
| 	ExtendedErrorCodeNoReachableAuthority | ||||
| 	ExtendedErrorCodeNetworkError | ||||
| 	ExtendedErrorCodeInvalidData | ||||
| ) | ||||
| 
 | ||||
| // ExtendedErrorCodeToString maps extended error info codes to a human readable | ||||
| // description. | ||||
| var ExtendedErrorCodeToString = map[uint16]string{ | ||||
| 	ExtendedErrorCodeOther:                      "Other", | ||||
| 	ExtendedErrorCodeUnsupportedDNSKEYAlgorithm: "Unsupported DNSKEY Algorithm", | ||||
| 	ExtendedErrorCodeUnsupportedDSDigestType:    "Unsupported DS Digest Type", | ||||
| 	ExtendedErrorCodeStaleAnswer:                "Stale Answer", | ||||
| 	ExtendedErrorCodeForgedAnswer:               "Forged Answer", | ||||
| 	ExtendedErrorCodeDNSSECIndeterminate:        "DNSSEC Indeterminate", | ||||
| 	ExtendedErrorCodeDNSBogus:                   "DNSSEC Bogus", | ||||
| 	ExtendedErrorCodeSignatureExpired:           "Signature Expired", | ||||
| 	ExtendedErrorCodeSignatureNotYetValid:       "Signature Not Yet Valid", | ||||
| 	ExtendedErrorCodeDNSKEYMissing:              "DNSKEY Missing", | ||||
| 	ExtendedErrorCodeRRSIGsMissing:              "RRSIGs Missing", | ||||
| 	ExtendedErrorCodeNoZoneKeyBitSet:            "No Zone Key Bit Set", | ||||
| 	ExtendedErrorCodeNSECMissing:                "NSEC Missing", | ||||
| 	ExtendedErrorCodeCachedError:                "Cached Error", | ||||
| 	ExtendedErrorCodeNotReady:                   "Not Ready", | ||||
| 	ExtendedErrorCodeBlocked:                    "Blocked", | ||||
| 	ExtendedErrorCodeCensored:                   "Censored", | ||||
| 	ExtendedErrorCodeFiltered:                   "Filtered", | ||||
| 	ExtendedErrorCodeProhibited:                 "Prohibited", | ||||
| 	ExtendedErrorCodeStaleNXDOMAINAnswer:        "Stale NXDOMAIN Answer", | ||||
| 	ExtendedErrorCodeNotAuthoritative:           "Not Authoritative", | ||||
| 	ExtendedErrorCodeNotSupported:               "Not Supported", | ||||
| 	ExtendedErrorCodeNoReachableAuthority:       "No Reachable Authority", | ||||
| 	ExtendedErrorCodeNetworkError:               "Network Error", | ||||
| 	ExtendedErrorCodeInvalidData:                "Invalid Data", | ||||
| } | ||||
| 
 | ||||
| // StringToExtendedErrorCode is a map from human readable descriptions to | ||||
| // extended error info codes. | ||||
| var StringToExtendedErrorCode = reverseInt16(ExtendedErrorCodeToString) | ||||
| 
 | ||||
| // EDNS0_EDE option is used to return additional information about the cause of | ||||
| // DNS errors. | ||||
| type EDNS0_EDE struct { | ||||
| 	InfoCode  uint16 | ||||
| 	ExtraText string | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_EDE) Option() uint16 { return EDNS0EDE } | ||||
| func (e *EDNS0_EDE) copy() EDNS0    { return &EDNS0_EDE{e.InfoCode, e.ExtraText} } | ||||
| 
 | ||||
| func (e *EDNS0_EDE) String() string { | ||||
| 	info := strconv.FormatUint(uint64(e.InfoCode), 10) | ||||
| 	if s, ok := ExtendedErrorCodeToString[e.InfoCode]; ok { | ||||
| 		info += fmt.Sprintf(" (%s)", s) | ||||
| 	} | ||||
| 	return fmt.Sprintf("%s: (%s)", info, e.ExtraText) | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_EDE) pack() ([]byte, error) { | ||||
| 	b := make([]byte, 2+len(e.ExtraText)) | ||||
| 	binary.BigEndian.PutUint16(b[0:], e.InfoCode) | ||||
| 	copy(b[2:], []byte(e.ExtraText)) | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (e *EDNS0_EDE) unpack(b []byte) error { | ||||
| 	if len(b) < 2 { | ||||
| 		return ErrBuf | ||||
| 	} | ||||
| 	e.InfoCode = binary.BigEndian.Uint16(b[0:]) | ||||
| 	e.ExtraText = string(b[2:]) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // The EDNS0_ESU option for ENUM Source-URI Extension | ||||
| type EDNS0_ESU struct { | ||||
| 	Code uint16 | ||||
| 	Uri  string | ||||
| } | ||||
| 
 | ||||
| // Option implements the EDNS0 interface. | ||||
| func (e *EDNS0_ESU) Option() uint16        { return EDNS0ESU } | ||||
| func (e *EDNS0_ESU) String() string        { return e.Uri } | ||||
| func (e *EDNS0_ESU) copy() EDNS0           { return &EDNS0_ESU{e.Code, e.Uri} } | ||||
| func (e *EDNS0_ESU) pack() ([]byte, error) { return []byte(e.Uri), nil } | ||||
| func (e *EDNS0_ESU) unpack(b []byte) error { | ||||
| 	e.Uri = string(b) | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										93
									
								
								vendor/github.com/miekg/dns/format.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								vendor/github.com/miekg/dns/format.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,93 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"net" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| // NumField returns the number of rdata fields r has. | ||||
| func NumField(r RR) int { | ||||
| 	return reflect.ValueOf(r).Elem().NumField() - 1 // Remove RR_Header | ||||
| } | ||||
| 
 | ||||
| // Field returns the rdata field i as a string. Fields are indexed starting from 1. | ||||
| // RR types that holds slice data, for instance the NSEC type bitmap will return a single | ||||
| // string where the types are concatenated using a space. | ||||
| // Accessing non existing fields will cause a panic. | ||||
| func Field(r RR, i int) string { | ||||
| 	if i == 0 { | ||||
| 		return "" | ||||
| 	} | ||||
| 	d := reflect.ValueOf(r).Elem().Field(i) | ||||
| 	switch d.Kind() { | ||||
| 	case reflect.String: | ||||
| 		return d.String() | ||||
| 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||
| 		return strconv.FormatInt(d.Int(), 10) | ||||
| 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||
| 		return strconv.FormatUint(d.Uint(), 10) | ||||
| 	case reflect.Slice: | ||||
| 		switch reflect.ValueOf(r).Elem().Type().Field(i).Tag { | ||||
| 		case `dns:"a"`: | ||||
| 			// TODO(miek): Hmm store this as 16 bytes | ||||
| 			if d.Len() < net.IPv4len { | ||||
| 				return "" | ||||
| 			} | ||||
| 			if d.Len() < net.IPv6len { | ||||
| 				return net.IPv4(byte(d.Index(0).Uint()), | ||||
| 					byte(d.Index(1).Uint()), | ||||
| 					byte(d.Index(2).Uint()), | ||||
| 					byte(d.Index(3).Uint())).String() | ||||
| 			} | ||||
| 			return net.IPv4(byte(d.Index(12).Uint()), | ||||
| 				byte(d.Index(13).Uint()), | ||||
| 				byte(d.Index(14).Uint()), | ||||
| 				byte(d.Index(15).Uint())).String() | ||||
| 		case `dns:"aaaa"`: | ||||
| 			if d.Len() < net.IPv6len { | ||||
| 				return "" | ||||
| 			} | ||||
| 			return net.IP{ | ||||
| 				byte(d.Index(0).Uint()), | ||||
| 				byte(d.Index(1).Uint()), | ||||
| 				byte(d.Index(2).Uint()), | ||||
| 				byte(d.Index(3).Uint()), | ||||
| 				byte(d.Index(4).Uint()), | ||||
| 				byte(d.Index(5).Uint()), | ||||
| 				byte(d.Index(6).Uint()), | ||||
| 				byte(d.Index(7).Uint()), | ||||
| 				byte(d.Index(8).Uint()), | ||||
| 				byte(d.Index(9).Uint()), | ||||
| 				byte(d.Index(10).Uint()), | ||||
| 				byte(d.Index(11).Uint()), | ||||
| 				byte(d.Index(12).Uint()), | ||||
| 				byte(d.Index(13).Uint()), | ||||
| 				byte(d.Index(14).Uint()), | ||||
| 				byte(d.Index(15).Uint()), | ||||
| 			}.String() | ||||
| 		case `dns:"nsec"`: | ||||
| 			if d.Len() == 0 { | ||||
| 				return "" | ||||
| 			} | ||||
| 			s := Type(d.Index(0).Uint()).String() | ||||
| 			for i := 1; i < d.Len(); i++ { | ||||
| 				s += " " + Type(d.Index(i).Uint()).String() | ||||
| 			} | ||||
| 			return s | ||||
| 		default: | ||||
| 			// if it does not have a tag its a string slice | ||||
| 			fallthrough | ||||
| 		case `dns:"txt"`: | ||||
| 			if d.Len() == 0 { | ||||
| 				return "" | ||||
| 			} | ||||
| 			s := d.Index(0).String() | ||||
| 			for i := 1; i < d.Len(); i++ { | ||||
| 				s += " " + d.Index(i).String() | ||||
| 			} | ||||
| 			return s | ||||
| 		} | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
							
								
								
									
										32
									
								
								vendor/github.com/miekg/dns/fuzz.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/github.com/miekg/dns/fuzz.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| // +build fuzz | ||||
| 
 | ||||
| package dns | ||||
| 
 | ||||
| import "strings" | ||||
| 
 | ||||
| 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 { | ||||
| 	str := string(data) | ||||
| 	// Do not fuzz lines that include the $INCLUDE keyword and hint the fuzzer | ||||
| 	// at avoiding them. | ||||
| 	// See GH#1025 for context. | ||||
| 	if strings.Contains(strings.ToUpper(str), "$INCLUDE") { | ||||
| 		return -1 | ||||
| 	} | ||||
| 	if _, err := NewRR(str); err != nil { | ||||
| 		return 0 | ||||
| 	} | ||||
| 	return 1 | ||||
| } | ||||
							
								
								
									
										247
									
								
								vendor/github.com/miekg/dns/generate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								vendor/github.com/miekg/dns/generate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,247 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // Parse the $GENERATE statement as used in BIND9 zones. | ||||
| // See http://www.zytrax.com/books/dns/ch8/generate.html for instance. | ||||
| // We are called after '$GENERATE '. After which we expect: | ||||
| // * the range (12-24/2) | ||||
| // * lhs (ownername) | ||||
| // * [[ttl][class]] | ||||
| // * type | ||||
| // * rhs (rdata) | ||||
| // But we are lazy here, only the range is parsed *all* occurrences | ||||
| // of $ after that are interpreted. | ||||
| func (zp *ZoneParser) generate(l lex) (RR, bool) { | ||||
| 	token := l.token | ||||
| 	step := int64(1) | ||||
| 	if i := strings.IndexByte(token, '/'); i >= 0 { | ||||
| 		if i+1 == len(token) { | ||||
| 			return zp.setParseError("bad step in $GENERATE range", l) | ||||
| 		} | ||||
| 
 | ||||
| 		s, err := strconv.ParseInt(token[i+1:], 10, 64) | ||||
| 		if err != nil || s <= 0 { | ||||
| 			return zp.setParseError("bad step in $GENERATE range", l) | ||||
| 		} | ||||
| 
 | ||||
| 		step = s | ||||
| 		token = token[:i] | ||||
| 	} | ||||
| 
 | ||||
| 	sx := strings.SplitN(token, "-", 2) | ||||
| 	if len(sx) != 2 { | ||||
| 		return zp.setParseError("bad start-stop in $GENERATE range", l) | ||||
| 	} | ||||
| 
 | ||||
| 	start, err := strconv.ParseInt(sx[0], 10, 64) | ||||
| 	if err != nil { | ||||
| 		return zp.setParseError("bad start in $GENERATE range", l) | ||||
| 	} | ||||
| 
 | ||||
| 	end, err := strconv.ParseInt(sx[1], 10, 64) | ||||
| 	if err != nil { | ||||
| 		return zp.setParseError("bad stop in $GENERATE range", l) | ||||
| 	} | ||||
| 	if end < 0 || start < 0 || end < start || (end-start)/step > 65535 { | ||||
| 		return zp.setParseError("bad range in $GENERATE range", l) | ||||
| 	} | ||||
| 
 | ||||
| 	// _BLANK | ||||
| 	l, ok := zp.c.Next() | ||||
| 	if !ok || l.value != zBlank { | ||||
| 		return zp.setParseError("garbage after $GENERATE range", l) | ||||
| 	} | ||||
| 
 | ||||
| 	// Create a complete new string, which we then parse again. | ||||
| 	var s string | ||||
| 	for l, ok := zp.c.Next(); ok; l, ok = zp.c.Next() { | ||||
| 		if l.err { | ||||
| 			return zp.setParseError("bad data in $GENERATE directive", l) | ||||
| 		} | ||||
| 		if l.value == zNewline { | ||||
| 			break | ||||
| 		} | ||||
| 
 | ||||
| 		s += l.token | ||||
| 	} | ||||
| 
 | ||||
| 	r := &generateReader{ | ||||
| 		s: s, | ||||
| 
 | ||||
| 		cur:   start, | ||||
| 		start: start, | ||||
| 		end:   end, | ||||
| 		step:  step, | ||||
| 
 | ||||
| 		file: zp.file, | ||||
| 		lex:  &l, | ||||
| 	} | ||||
| 	zp.sub = NewZoneParser(r, zp.origin, zp.file) | ||||
| 	zp.sub.includeDepth, zp.sub.includeAllowed = zp.includeDepth, zp.includeAllowed | ||||
| 	zp.sub.generateDisallowed = true | ||||
| 	zp.sub.SetDefaultTTL(defaultTtl) | ||||
| 	return zp.subNext() | ||||
| } | ||||
| 
 | ||||
| type generateReader struct { | ||||
| 	s  string | ||||
| 	si int | ||||
| 
 | ||||
| 	cur   int64 | ||||
| 	start int64 | ||||
| 	end   int64 | ||||
| 	step  int64 | ||||
| 
 | ||||
| 	mod bytes.Buffer | ||||
| 
 | ||||
| 	escape bool | ||||
| 
 | ||||
| 	eof bool | ||||
| 
 | ||||
| 	file string | ||||
| 	lex  *lex | ||||
| } | ||||
| 
 | ||||
| func (r *generateReader) parseError(msg string, end int) *ParseError { | ||||
| 	r.eof = true // Make errors sticky. | ||||
| 
 | ||||
| 	l := *r.lex | ||||
| 	l.token = r.s[r.si-1 : end] | ||||
| 	l.column += r.si // l.column starts one zBLANK before r.s | ||||
| 
 | ||||
| 	return &ParseError{r.file, msg, l} | ||||
| } | ||||
| 
 | ||||
| func (r *generateReader) Read(p []byte) (int, error) { | ||||
| 	// NewZLexer, through NewZoneParser, should use ReadByte and | ||||
| 	// not end up here. | ||||
| 
 | ||||
| 	panic("not implemented") | ||||
| } | ||||
| 
 | ||||
| func (r *generateReader) ReadByte() (byte, error) { | ||||
| 	if r.eof { | ||||
| 		return 0, io.EOF | ||||
| 	} | ||||
| 	if r.mod.Len() > 0 { | ||||
| 		return r.mod.ReadByte() | ||||
| 	} | ||||
| 
 | ||||
| 	if r.si >= len(r.s) { | ||||
| 		r.si = 0 | ||||
| 		r.cur += r.step | ||||
| 
 | ||||
| 		r.eof = r.cur > r.end || r.cur < 0 | ||||
| 		return '\n', nil | ||||
| 	} | ||||
| 
 | ||||
| 	si := r.si | ||||
| 	r.si++ | ||||
| 
 | ||||
| 	switch r.s[si] { | ||||
| 	case '\\': | ||||
| 		if r.escape { | ||||
| 			r.escape = false | ||||
| 			return '\\', nil | ||||
| 		} | ||||
| 
 | ||||
| 		r.escape = true | ||||
| 		return r.ReadByte() | ||||
| 	case '$': | ||||
| 		if r.escape { | ||||
| 			r.escape = false | ||||
| 			return '$', nil | ||||
| 		} | ||||
| 
 | ||||
| 		mod := "%d" | ||||
| 
 | ||||
| 		if si >= len(r.s)-1 { | ||||
| 			// End of the string | ||||
| 			fmt.Fprintf(&r.mod, mod, r.cur) | ||||
| 			return r.mod.ReadByte() | ||||
| 		} | ||||
| 
 | ||||
| 		if r.s[si+1] == '$' { | ||||
| 			r.si++ | ||||
| 			return '$', nil | ||||
| 		} | ||||
| 
 | ||||
| 		var offset int64 | ||||
| 
 | ||||
| 		// Search for { and } | ||||
| 		if r.s[si+1] == '{' { | ||||
| 			// Modifier block | ||||
| 			sep := strings.Index(r.s[si+2:], "}") | ||||
| 			if sep < 0 { | ||||
| 				return 0, r.parseError("bad modifier in $GENERATE", len(r.s)) | ||||
| 			} | ||||
| 
 | ||||
| 			var errMsg string | ||||
| 			mod, offset, errMsg = modToPrintf(r.s[si+2 : si+2+sep]) | ||||
| 			if errMsg != "" { | ||||
| 				return 0, r.parseError(errMsg, si+3+sep) | ||||
| 			} | ||||
| 			if r.start+offset < 0 || r.end+offset > 1<<31-1 { | ||||
| 				return 0, r.parseError("bad offset in $GENERATE", si+3+sep) | ||||
| 			} | ||||
| 
 | ||||
| 			r.si += 2 + sep // Jump to it | ||||
| 		} | ||||
| 
 | ||||
| 		fmt.Fprintf(&r.mod, mod, r.cur+offset) | ||||
| 		return r.mod.ReadByte() | ||||
| 	default: | ||||
| 		if r.escape { // Pretty useless here | ||||
| 			r.escape = false | ||||
| 			return r.ReadByte() | ||||
| 		} | ||||
| 
 | ||||
| 		return r.s[si], nil | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Convert a $GENERATE modifier 0,0,d to something Printf can deal with. | ||||
| func modToPrintf(s string) (string, int64, string) { | ||||
| 	// Modifier is { offset [ ,width [ ,base ] ] } - provide default | ||||
| 	// values for optional width and type, if necessary. | ||||
| 	var offStr, widthStr, base string | ||||
| 	switch xs := strings.Split(s, ","); len(xs) { | ||||
| 	case 1: | ||||
| 		offStr, widthStr, base = xs[0], "0", "d" | ||||
| 	case 2: | ||||
| 		offStr, widthStr, base = xs[0], xs[1], "d" | ||||
| 	case 3: | ||||
| 		offStr, widthStr, base = xs[0], xs[1], xs[2] | ||||
| 	default: | ||||
| 		return "", 0, "bad modifier in $GENERATE" | ||||
| 	} | ||||
| 
 | ||||
| 	switch base { | ||||
| 	case "o", "d", "x", "X": | ||||
| 	default: | ||||
| 		return "", 0, "bad base in $GENERATE" | ||||
| 	} | ||||
| 
 | ||||
| 	offset, err := strconv.ParseInt(offStr, 10, 64) | ||||
| 	if err != nil { | ||||
| 		return "", 0, "bad offset in $GENERATE" | ||||
| 	} | ||||
| 
 | ||||
| 	width, err := strconv.ParseInt(widthStr, 10, 64) | ||||
| 	if err != nil || width < 0 || width > 255 { | ||||
| 		return "", 0, "bad width in $GENERATE" | ||||
| 	} | ||||
| 
 | ||||
| 	if width == 0 { | ||||
| 		return "%" + base, offset, "" | ||||
| 	} | ||||
| 
 | ||||
| 	return "%0" + widthStr + base, offset, "" | ||||
| } | ||||
							
								
								
									
										31
									
								
								vendor/github.com/miekg/dns/hash.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/miekg/dns/hash.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"crypto" | ||||
| 	"hash" | ||||
| ) | ||||
| 
 | ||||
| // identityHash will not hash, it only buffers the data written into it and returns it as-is. | ||||
| type identityHash struct { | ||||
| 	b *bytes.Buffer | ||||
| } | ||||
| 
 | ||||
| // Implement the hash.Hash interface. | ||||
| 
 | ||||
| func (i identityHash) Write(b []byte) (int, error) { return i.b.Write(b) } | ||||
| func (i identityHash) Size() int                   { return i.b.Len() } | ||||
| func (i identityHash) BlockSize() int              { return 1024 } | ||||
| func (i identityHash) Reset()                      { i.b.Reset() } | ||||
| func (i identityHash) Sum(b []byte) []byte         { return append(b, i.b.Bytes()...) } | ||||
| 
 | ||||
| func hashFromAlgorithm(alg uint8) (hash.Hash, crypto.Hash, error) { | ||||
| 	hashnumber, ok := AlgorithmToHash[alg] | ||||
| 	if !ok { | ||||
| 		return nil, 0, ErrAlg | ||||
| 	} | ||||
| 	if hashnumber == 0 { | ||||
| 		return identityHash{b: &bytes.Buffer{}}, hashnumber, nil | ||||
| 	} | ||||
| 	return hashnumber.New(), hashnumber, nil | ||||
| } | ||||
							
								
								
									
										212
									
								
								vendor/github.com/miekg/dns/labels.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								vendor/github.com/miekg/dns/labels.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,212 @@ | |||
| package dns | ||||
| 
 | ||||
| // Holds a bunch of helper functions for dealing with labels. | ||||
| 
 | ||||
| // SplitDomainName splits a name string into it's labels. | ||||
| // www.miek.nl. returns []string{"www", "miek", "nl"} | ||||
| // .www.miek.nl. returns []string{"", "www", "miek", "nl"}, | ||||
| // The root label (.) returns nil. Note that using | ||||
| // strings.Split(s) will work in most cases, but does not handle | ||||
| // escaped dots (\.) for instance. | ||||
| // s must be a syntactically valid domain name, see IsDomainName. | ||||
| func SplitDomainName(s string) (labels []string) { | ||||
| 	if s == "" { | ||||
| 		return nil | ||||
| 	} | ||||
| 	fqdnEnd := 0 // offset of the final '.' or the length of the name | ||||
| 	idx := Split(s) | ||||
| 	begin := 0 | ||||
| 	if IsFqdn(s) { | ||||
| 		fqdnEnd = len(s) - 1 | ||||
| 	} else { | ||||
| 		fqdnEnd = len(s) | ||||
| 	} | ||||
| 
 | ||||
| 	switch len(idx) { | ||||
| 	case 0: | ||||
| 		return nil | ||||
| 	case 1: | ||||
| 		// no-op | ||||
| 	default: | ||||
| 		for _, end := range idx[1:] { | ||||
| 			labels = append(labels, s[begin:end-1]) | ||||
| 			begin = end | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return append(labels, s[begin:fqdnEnd]) | ||||
| } | ||||
| 
 | ||||
| // CompareDomainName compares the names s1 and s2 and | ||||
| // returns how many labels they have in common starting from the *right*. | ||||
| // The comparison stops at the first inequality. The names are downcased | ||||
| // before the comparison. | ||||
| // | ||||
| // www.miek.nl. and miek.nl. have two labels in common: miek and nl | ||||
| // www.miek.nl. and www.bla.nl. have one label in common: nl | ||||
| // | ||||
| // s1 and s2 must be syntactically valid domain names. | ||||
| func CompareDomainName(s1, s2 string) (n int) { | ||||
| 	// the first check: root label | ||||
| 	if s1 == "." || s2 == "." { | ||||
| 		return 0 | ||||
| 	} | ||||
| 
 | ||||
| 	l1 := Split(s1) | ||||
| 	l2 := Split(s2) | ||||
| 
 | ||||
| 	j1 := len(l1) - 1 // end | ||||
| 	i1 := len(l1) - 2 // start | ||||
| 	j2 := len(l2) - 1 | ||||
| 	i2 := len(l2) - 2 | ||||
| 	// the second check can be done here: last/only label | ||||
| 	// before we fall through into the for-loop below | ||||
| 	if equal(s1[l1[j1]:], s2[l2[j2]:]) { | ||||
| 		n++ | ||||
| 	} else { | ||||
| 		return | ||||
| 	} | ||||
| 	for { | ||||
| 		if i1 < 0 || i2 < 0 { | ||||
| 			break | ||||
| 		} | ||||
| 		if equal(s1[l1[i1]:l1[j1]], s2[l2[i2]:l2[j2]]) { | ||||
| 			n++ | ||||
| 		} else { | ||||
| 			break | ||||
| 		} | ||||
| 		j1-- | ||||
| 		i1-- | ||||
| 		j2-- | ||||
| 		i2-- | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // CountLabel counts the number of labels in the string s. | ||||
| // s must be a syntactically valid domain name. | ||||
| func CountLabel(s string) (labels int) { | ||||
| 	if s == "." { | ||||
| 		return | ||||
| 	} | ||||
| 	off := 0 | ||||
| 	end := false | ||||
| 	for { | ||||
| 		off, end = NextLabel(s, off) | ||||
| 		labels++ | ||||
| 		if end { | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Split splits a name s into its label indexes. | ||||
| // www.miek.nl. returns []int{0, 4, 9}, www.miek.nl also returns []int{0, 4, 9}. | ||||
| // The root name (.) returns nil. Also see SplitDomainName. | ||||
| // s must be a syntactically valid domain name. | ||||
| func Split(s string) []int { | ||||
| 	if s == "." { | ||||
| 		return nil | ||||
| 	} | ||||
| 	idx := make([]int, 1, 3) | ||||
| 	off := 0 | ||||
| 	end := false | ||||
| 
 | ||||
| 	for { | ||||
| 		off, end = NextLabel(s, off) | ||||
| 		if end { | ||||
| 			return idx | ||||
| 		} | ||||
| 		idx = append(idx, off) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NextLabel returns the index of the start of the next label in the | ||||
| // string s starting at offset. | ||||
| // The bool end is true when the end of the string has been reached. | ||||
| // Also see PrevLabel. | ||||
| func NextLabel(s string, offset int) (i int, end bool) { | ||||
| 	if s == "" { | ||||
| 		return 0, true | ||||
| 	} | ||||
| 	for i = offset; i < len(s)-1; i++ { | ||||
| 		if s[i] != '.' { | ||||
| 			continue | ||||
| 		} | ||||
| 		j := i - 1 | ||||
| 		for j >= 0 && s[j] == '\\' { | ||||
| 			j-- | ||||
| 		} | ||||
| 
 | ||||
| 		if (j-i)%2 == 0 { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		return i + 1, false | ||||
| 	} | ||||
| 	return i + 1, true | ||||
| } | ||||
| 
 | ||||
| // PrevLabel returns the index of the label when starting from the right and | ||||
| // jumping n labels to the left. | ||||
| // The bool start is true when the start of the string has been overshot. | ||||
| // Also see NextLabel. | ||||
| func PrevLabel(s string, n int) (i int, start bool) { | ||||
| 	if s == "" { | ||||
| 		return 0, true | ||||
| 	} | ||||
| 	if n == 0 { | ||||
| 		return len(s), false | ||||
| 	} | ||||
| 
 | ||||
| 	l := len(s) - 1 | ||||
| 	if s[l] == '.' { | ||||
| 		l-- | ||||
| 	} | ||||
| 
 | ||||
| 	for ; l >= 0 && n > 0; l-- { | ||||
| 		if s[l] != '.' { | ||||
| 			continue | ||||
| 		} | ||||
| 		j := l - 1 | ||||
| 		for j >= 0 && s[j] == '\\' { | ||||
| 			j-- | ||||
| 		} | ||||
| 
 | ||||
| 		if (j-l)%2 == 0 { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		n-- | ||||
| 		if n == 0 { | ||||
| 			return l + 1, false | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0, n > 1 | ||||
| } | ||||
| 
 | ||||
| // equal compares a and b while ignoring case. It returns true when equal otherwise false. | ||||
| func equal(a, b string) bool { | ||||
| 	// might be lifted into API function. | ||||
| 	la := len(a) | ||||
| 	lb := len(b) | ||||
| 	if la != lb { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	for i := la - 1; i >= 0; i-- { | ||||
| 		ai := a[i] | ||||
| 		bi := b[i] | ||||
| 		if ai >= 'A' && ai <= 'Z' { | ||||
| 			ai |= 'a' - 'A' | ||||
| 		} | ||||
| 		if bi >= 'A' && bi <= 'Z' { | ||||
| 			bi |= 'a' - 'A' | ||||
| 		} | ||||
| 		if ai != bi { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
							
								
								
									
										23
									
								
								vendor/github.com/miekg/dns/listen_no_reuseport.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/miekg/dns/listen_no_reuseport.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| // +build !go1.11 !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd | ||||
| 
 | ||||
| package dns | ||||
| 
 | ||||
| import "net" | ||||
| 
 | ||||
| const supportsReusePort = false | ||||
| 
 | ||||
| func listenTCP(network, addr string, reuseport bool) (net.Listener, error) { | ||||
| 	if reuseport { | ||||
| 		// TODO(tmthrgd): return an error? | ||||
| 	} | ||||
| 
 | ||||
| 	return net.Listen(network, addr) | ||||
| } | ||||
| 
 | ||||
| func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) { | ||||
| 	if reuseport { | ||||
| 		// TODO(tmthrgd): return an error? | ||||
| 	} | ||||
| 
 | ||||
| 	return net.ListenPacket(network, addr) | ||||
| } | ||||
							
								
								
									
										44
									
								
								vendor/github.com/miekg/dns/listen_reuseport.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/miekg/dns/listen_reuseport.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| // +build go1.11 | ||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd | ||||
| 
 | ||||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"net" | ||||
| 	"syscall" | ||||
| 
 | ||||
| 	"golang.org/x/sys/unix" | ||||
| ) | ||||
| 
 | ||||
| const supportsReusePort = true | ||||
| 
 | ||||
| func reuseportControl(network, address string, c syscall.RawConn) error { | ||||
| 	var opErr error | ||||
| 	err := c.Control(func(fd uintptr) { | ||||
| 		opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1) | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	return opErr | ||||
| } | ||||
| 
 | ||||
| func listenTCP(network, addr string, reuseport bool) (net.Listener, error) { | ||||
| 	var lc net.ListenConfig | ||||
| 	if reuseport { | ||||
| 		lc.Control = reuseportControl | ||||
| 	} | ||||
| 
 | ||||
| 	return lc.Listen(context.Background(), network, addr) | ||||
| } | ||||
| 
 | ||||
| func listenUDP(network, addr string, reuseport bool) (net.PacketConn, error) { | ||||
| 	var lc net.ListenConfig | ||||
| 	if reuseport { | ||||
| 		lc.Control = reuseportControl | ||||
| 	} | ||||
| 
 | ||||
| 	return lc.ListenPacket(context.Background(), network, addr) | ||||
| } | ||||
							
								
								
									
										1202
									
								
								vendor/github.com/miekg/dns/msg.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1202
									
								
								vendor/github.com/miekg/dns/msg.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										812
									
								
								vendor/github.com/miekg/dns/msg_helpers.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										812
									
								
								vendor/github.com/miekg/dns/msg_helpers.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,812 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/base32" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/binary" | ||||
| 	"encoding/hex" | ||||
| 	"net" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // helper functions called from the generated zmsg.go | ||||
| 
 | ||||
| // These function are named after the tag to help pack/unpack, if there is no tag it is the name | ||||
| // of the type they pack/unpack (string, int, etc). We prefix all with unpackData or packData, so packDataA or | ||||
| // packDataDomainName. | ||||
| 
 | ||||
| func unpackDataA(msg []byte, off int) (net.IP, int, error) { | ||||
| 	if off+net.IPv4len > len(msg) { | ||||
| 		return nil, len(msg), &Error{err: "overflow unpacking a"} | ||||
| 	} | ||||
| 	a := append(make(net.IP, 0, net.IPv4len), msg[off:off+net.IPv4len]...) | ||||
| 	off += net.IPv4len | ||||
| 	return a, off, nil | ||||
| } | ||||
| 
 | ||||
| func packDataA(a net.IP, msg []byte, off int) (int, error) { | ||||
| 	switch len(a) { | ||||
| 	case net.IPv4len, net.IPv6len: | ||||
| 		// It must be a slice of 4, even if it is 16, we encode only the first 4 | ||||
| 		if off+net.IPv4len > len(msg) { | ||||
| 			return len(msg), &Error{err: "overflow packing a"} | ||||
| 		} | ||||
| 
 | ||||
| 		copy(msg[off:], a.To4()) | ||||
| 		off += net.IPv4len | ||||
| 	case 0: | ||||
| 		// Allowed, for dynamic updates. | ||||
| 	default: | ||||
| 		return len(msg), &Error{err: "overflow packing a"} | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackDataAAAA(msg []byte, off int) (net.IP, int, error) { | ||||
| 	if off+net.IPv6len > len(msg) { | ||||
| 		return nil, len(msg), &Error{err: "overflow unpacking aaaa"} | ||||
| 	} | ||||
| 	aaaa := append(make(net.IP, 0, net.IPv6len), msg[off:off+net.IPv6len]...) | ||||
| 	off += net.IPv6len | ||||
| 	return aaaa, off, nil | ||||
| } | ||||
| 
 | ||||
| func packDataAAAA(aaaa net.IP, msg []byte, off int) (int, error) { | ||||
| 	switch len(aaaa) { | ||||
| 	case net.IPv6len: | ||||
| 		if off+net.IPv6len > len(msg) { | ||||
| 			return len(msg), &Error{err: "overflow packing aaaa"} | ||||
| 		} | ||||
| 
 | ||||
| 		copy(msg[off:], aaaa) | ||||
| 		off += net.IPv6len | ||||
| 	case 0: | ||||
| 		// Allowed, dynamic updates. | ||||
| 	default: | ||||
| 		return len(msg), &Error{err: "overflow packing aaaa"} | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| // unpackHeader unpacks an RR header, returning the offset to the end of the header and a | ||||
| // re-sliced msg according to the expected length of the RR. | ||||
| func unpackHeader(msg []byte, off int) (rr RR_Header, off1 int, truncmsg []byte, err error) { | ||||
| 	hdr := RR_Header{} | ||||
| 	if off == len(msg) { | ||||
| 		return hdr, off, msg, nil | ||||
| 	} | ||||
| 
 | ||||
| 	hdr.Name, off, err = UnpackDomainName(msg, off) | ||||
| 	if err != nil { | ||||
| 		return hdr, len(msg), msg, err | ||||
| 	} | ||||
| 	hdr.Rrtype, off, err = unpackUint16(msg, off) | ||||
| 	if err != nil { | ||||
| 		return hdr, len(msg), msg, err | ||||
| 	} | ||||
| 	hdr.Class, off, err = unpackUint16(msg, off) | ||||
| 	if err != nil { | ||||
| 		return hdr, len(msg), msg, err | ||||
| 	} | ||||
| 	hdr.Ttl, off, err = unpackUint32(msg, off) | ||||
| 	if err != nil { | ||||
| 		return hdr, len(msg), msg, err | ||||
| 	} | ||||
| 	hdr.Rdlength, off, err = unpackUint16(msg, off) | ||||
| 	if err != nil { | ||||
| 		return hdr, len(msg), msg, err | ||||
| 	} | ||||
| 	msg, err = truncateMsgFromRdlength(msg, off, hdr.Rdlength) | ||||
| 	return hdr, off, msg, err | ||||
| } | ||||
| 
 | ||||
| // packHeader packs an RR header, returning the offset to the end of the header. | ||||
| // See PackDomainName for documentation about the compression. | ||||
| func (hdr RR_Header) packHeader(msg []byte, off int, compression compressionMap, compress bool) (int, error) { | ||||
| 	if off == len(msg) { | ||||
| 		return off, nil | ||||
| 	} | ||||
| 
 | ||||
| 	off, err := packDomainName(hdr.Name, msg, off, compression, compress) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	off, err = packUint16(hdr.Rrtype, msg, off) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	off, err = packUint16(hdr.Class, msg, off) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	off, err = packUint32(hdr.Ttl, msg, off) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	off, err = packUint16(0, msg, off) // The RDLENGTH field will be set later in packRR. | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| // helper helper functions. | ||||
| 
 | ||||
| // truncateMsgFromRdLength truncates msg to match the expected length of the RR. | ||||
| // Returns an error if msg is smaller than the expected size. | ||||
| func truncateMsgFromRdlength(msg []byte, off int, rdlength uint16) (truncmsg []byte, err error) { | ||||
| 	lenrd := off + int(rdlength) | ||||
| 	if lenrd > len(msg) { | ||||
| 		return msg, &Error{err: "overflowing header size"} | ||||
| 	} | ||||
| 	return msg[:lenrd], nil | ||||
| } | ||||
| 
 | ||||
| var base32HexNoPadEncoding = base32.HexEncoding.WithPadding(base32.NoPadding) | ||||
| 
 | ||||
| func fromBase32(s []byte) (buf []byte, err error) { | ||||
| 	for i, b := range s { | ||||
| 		if b >= 'a' && b <= 'z' { | ||||
| 			s[i] = b - 32 | ||||
| 		} | ||||
| 	} | ||||
| 	buflen := base32HexNoPadEncoding.DecodedLen(len(s)) | ||||
| 	buf = make([]byte, buflen) | ||||
| 	n, err := base32HexNoPadEncoding.Decode(buf, s) | ||||
| 	buf = buf[:n] | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func toBase32(b []byte) string { | ||||
| 	return base32HexNoPadEncoding.EncodeToString(b) | ||||
| } | ||||
| 
 | ||||
| func fromBase64(s []byte) (buf []byte, err error) { | ||||
| 	buflen := base64.StdEncoding.DecodedLen(len(s)) | ||||
| 	buf = make([]byte, buflen) | ||||
| 	n, err := base64.StdEncoding.Decode(buf, s) | ||||
| 	buf = buf[:n] | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func toBase64(b []byte) string { return base64.StdEncoding.EncodeToString(b) } | ||||
| 
 | ||||
| // dynamicUpdate returns true if the Rdlength is zero. | ||||
| func noRdata(h RR_Header) bool { return h.Rdlength == 0 } | ||||
| 
 | ||||
| func unpackUint8(msg []byte, off int) (i uint8, off1 int, err error) { | ||||
| 	if off+1 > len(msg) { | ||||
| 		return 0, len(msg), &Error{err: "overflow unpacking uint8"} | ||||
| 	} | ||||
| 	return msg[off], off + 1, nil | ||||
| } | ||||
| 
 | ||||
| func packUint8(i uint8, msg []byte, off int) (off1 int, err error) { | ||||
| 	if off+1 > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing uint8"} | ||||
| 	} | ||||
| 	msg[off] = i | ||||
| 	return off + 1, nil | ||||
| } | ||||
| 
 | ||||
| func unpackUint16(msg []byte, off int) (i uint16, off1 int, err error) { | ||||
| 	if off+2 > len(msg) { | ||||
| 		return 0, len(msg), &Error{err: "overflow unpacking uint16"} | ||||
| 	} | ||||
| 	return binary.BigEndian.Uint16(msg[off:]), off + 2, nil | ||||
| } | ||||
| 
 | ||||
| func packUint16(i uint16, msg []byte, off int) (off1 int, err error) { | ||||
| 	if off+2 > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing uint16"} | ||||
| 	} | ||||
| 	binary.BigEndian.PutUint16(msg[off:], i) | ||||
| 	return off + 2, nil | ||||
| } | ||||
| 
 | ||||
| func unpackUint32(msg []byte, off int) (i uint32, off1 int, err error) { | ||||
| 	if off+4 > len(msg) { | ||||
| 		return 0, len(msg), &Error{err: "overflow unpacking uint32"} | ||||
| 	} | ||||
| 	return binary.BigEndian.Uint32(msg[off:]), off + 4, nil | ||||
| } | ||||
| 
 | ||||
| func packUint32(i uint32, msg []byte, off int) (off1 int, err error) { | ||||
| 	if off+4 > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing uint32"} | ||||
| 	} | ||||
| 	binary.BigEndian.PutUint32(msg[off:], i) | ||||
| 	return off + 4, nil | ||||
| } | ||||
| 
 | ||||
| func unpackUint48(msg []byte, off int) (i uint64, off1 int, err error) { | ||||
| 	if off+6 > len(msg) { | ||||
| 		return 0, len(msg), &Error{err: "overflow unpacking uint64 as uint48"} | ||||
| 	} | ||||
| 	// Used in TSIG where the last 48 bits are occupied, so for now, assume a uint48 (6 bytes) | ||||
| 	i = uint64(msg[off])<<40 | uint64(msg[off+1])<<32 | uint64(msg[off+2])<<24 | uint64(msg[off+3])<<16 | | ||||
| 		uint64(msg[off+4])<<8 | uint64(msg[off+5]) | ||||
| 	off += 6 | ||||
| 	return i, off, nil | ||||
| } | ||||
| 
 | ||||
| func packUint48(i uint64, msg []byte, off int) (off1 int, err error) { | ||||
| 	if off+6 > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing uint64 as uint48"} | ||||
| 	} | ||||
| 	msg[off] = byte(i >> 40) | ||||
| 	msg[off+1] = byte(i >> 32) | ||||
| 	msg[off+2] = byte(i >> 24) | ||||
| 	msg[off+3] = byte(i >> 16) | ||||
| 	msg[off+4] = byte(i >> 8) | ||||
| 	msg[off+5] = byte(i) | ||||
| 	off += 6 | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackUint64(msg []byte, off int) (i uint64, off1 int, err error) { | ||||
| 	if off+8 > len(msg) { | ||||
| 		return 0, len(msg), &Error{err: "overflow unpacking uint64"} | ||||
| 	} | ||||
| 	return binary.BigEndian.Uint64(msg[off:]), off + 8, nil | ||||
| } | ||||
| 
 | ||||
| func packUint64(i uint64, msg []byte, off int) (off1 int, err error) { | ||||
| 	if off+8 > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing uint64"} | ||||
| 	} | ||||
| 	binary.BigEndian.PutUint64(msg[off:], i) | ||||
| 	off += 8 | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackString(msg []byte, off int) (string, int, error) { | ||||
| 	if off+1 > len(msg) { | ||||
| 		return "", off, &Error{err: "overflow unpacking txt"} | ||||
| 	} | ||||
| 	l := int(msg[off]) | ||||
| 	off++ | ||||
| 	if off+l > len(msg) { | ||||
| 		return "", off, &Error{err: "overflow unpacking txt"} | ||||
| 	} | ||||
| 	var s strings.Builder | ||||
| 	consumed := 0 | ||||
| 	for i, b := range msg[off : off+l] { | ||||
| 		switch { | ||||
| 		case b == '"' || b == '\\': | ||||
| 			if consumed == 0 { | ||||
| 				s.Grow(l * 2) | ||||
| 			} | ||||
| 			s.Write(msg[off+consumed : off+i]) | ||||
| 			s.WriteByte('\\') | ||||
| 			s.WriteByte(b) | ||||
| 			consumed = i + 1 | ||||
| 		case b < ' ' || b > '~': // unprintable | ||||
| 			if consumed == 0 { | ||||
| 				s.Grow(l * 2) | ||||
| 			} | ||||
| 			s.Write(msg[off+consumed : off+i]) | ||||
| 			s.WriteString(escapeByte(b)) | ||||
| 			consumed = i + 1 | ||||
| 		} | ||||
| 	} | ||||
| 	if consumed == 0 { // no escaping needed | ||||
| 		return string(msg[off : off+l]), off + l, nil | ||||
| 	} | ||||
| 	s.Write(msg[off+consumed : off+l]) | ||||
| 	return s.String(), off + l, nil | ||||
| } | ||||
| 
 | ||||
| func packString(s string, msg []byte, off int) (int, error) { | ||||
| 	txtTmp := make([]byte, 256*4+1) | ||||
| 	off, err := packTxtString(s, msg, off, txtTmp) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackStringBase32(msg []byte, off, end int) (string, int, error) { | ||||
| 	if end > len(msg) { | ||||
| 		return "", len(msg), &Error{err: "overflow unpacking base32"} | ||||
| 	} | ||||
| 	s := toBase32(msg[off:end]) | ||||
| 	return s, end, nil | ||||
| } | ||||
| 
 | ||||
| func packStringBase32(s string, msg []byte, off int) (int, error) { | ||||
| 	b32, err := fromBase32([]byte(s)) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	if off+len(b32) > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing base32"} | ||||
| 	} | ||||
| 	copy(msg[off:off+len(b32)], b32) | ||||
| 	off += len(b32) | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackStringBase64(msg []byte, off, end int) (string, int, error) { | ||||
| 	// Rest of the RR is base64 encoded value, so we don't need an explicit length | ||||
| 	// to be set. Thus far all RR's that have base64 encoded fields have those as their | ||||
| 	// last one. What we do need is the end of the RR! | ||||
| 	if end > len(msg) { | ||||
| 		return "", len(msg), &Error{err: "overflow unpacking base64"} | ||||
| 	} | ||||
| 	s := toBase64(msg[off:end]) | ||||
| 	return s, end, nil | ||||
| } | ||||
| 
 | ||||
| func packStringBase64(s string, msg []byte, off int) (int, error) { | ||||
| 	b64, err := fromBase64([]byte(s)) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	if off+len(b64) > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing base64"} | ||||
| 	} | ||||
| 	copy(msg[off:off+len(b64)], b64) | ||||
| 	off += len(b64) | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackStringHex(msg []byte, off, end int) (string, int, error) { | ||||
| 	// Rest of the RR is hex encoded value, so we don't need an explicit length | ||||
| 	// to be set. NSEC and TSIG have hex fields with a length field. | ||||
| 	// What we do need is the end of the RR! | ||||
| 	if end > len(msg) { | ||||
| 		return "", len(msg), &Error{err: "overflow unpacking hex"} | ||||
| 	} | ||||
| 
 | ||||
| 	s := hex.EncodeToString(msg[off:end]) | ||||
| 	return s, end, nil | ||||
| } | ||||
| 
 | ||||
| func packStringHex(s string, msg []byte, off int) (int, error) { | ||||
| 	h, err := hex.DecodeString(s) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	if off+len(h) > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing hex"} | ||||
| 	} | ||||
| 	copy(msg[off:off+len(h)], h) | ||||
| 	off += len(h) | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackStringAny(msg []byte, off, end int) (string, int, error) { | ||||
| 	if end > len(msg) { | ||||
| 		return "", len(msg), &Error{err: "overflow unpacking anything"} | ||||
| 	} | ||||
| 	return string(msg[off:end]), end, nil | ||||
| } | ||||
| 
 | ||||
| func packStringAny(s string, msg []byte, off int) (int, error) { | ||||
| 	if off+len(s) > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing anything"} | ||||
| 	} | ||||
| 	copy(msg[off:off+len(s)], s) | ||||
| 	off += len(s) | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackStringTxt(msg []byte, off int) ([]string, int, error) { | ||||
| 	txt, off, err := unpackTxt(msg, off) | ||||
| 	if err != nil { | ||||
| 		return nil, len(msg), err | ||||
| 	} | ||||
| 	return txt, off, nil | ||||
| } | ||||
| 
 | ||||
| func packStringTxt(s []string, msg []byte, off int) (int, error) { | ||||
| 	txtTmp := make([]byte, 256*4+1) // If the whole string consists out of \DDD we need this many. | ||||
| 	off, err := packTxt(s, msg, off, txtTmp) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackDataOpt(msg []byte, off int) ([]EDNS0, int, error) { | ||||
| 	var edns []EDNS0 | ||||
| Option: | ||||
| 	var code uint16 | ||||
| 	if off+4 > len(msg) { | ||||
| 		return nil, len(msg), &Error{err: "overflow unpacking opt"} | ||||
| 	} | ||||
| 	code = binary.BigEndian.Uint16(msg[off:]) | ||||
| 	off += 2 | ||||
| 	optlen := binary.BigEndian.Uint16(msg[off:]) | ||||
| 	off += 2 | ||||
| 	if off+int(optlen) > len(msg) { | ||||
| 		return nil, len(msg), &Error{err: "overflow unpacking opt"} | ||||
| 	} | ||||
| 	e := makeDataOpt(code) | ||||
| 	if err := e.unpack(msg[off : off+int(optlen)]); err != nil { | ||||
| 		return nil, len(msg), err | ||||
| 	} | ||||
| 	edns = append(edns, e) | ||||
| 	off += int(optlen) | ||||
| 
 | ||||
| 	if off < len(msg) { | ||||
| 		goto Option | ||||
| 	} | ||||
| 
 | ||||
| 	return edns, off, nil | ||||
| } | ||||
| 
 | ||||
| func packDataOpt(options []EDNS0, msg []byte, off int) (int, error) { | ||||
| 	for _, el := range options { | ||||
| 		b, err := el.pack() | ||||
| 		if err != nil || off+4 > len(msg) { | ||||
| 			return len(msg), &Error{err: "overflow packing opt"} | ||||
| 		} | ||||
| 		binary.BigEndian.PutUint16(msg[off:], el.Option())      // Option code | ||||
| 		binary.BigEndian.PutUint16(msg[off+2:], uint16(len(b))) // Length | ||||
| 		off += 4 | ||||
| 		if off+len(b) > len(msg) { | ||||
| 			return len(msg), &Error{err: "overflow packing opt"} | ||||
| 		} | ||||
| 		// Actual data | ||||
| 		copy(msg[off:off+len(b)], b) | ||||
| 		off += len(b) | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackStringOctet(msg []byte, off int) (string, int, error) { | ||||
| 	s := string(msg[off:]) | ||||
| 	return s, len(msg), nil | ||||
| } | ||||
| 
 | ||||
| func packStringOctet(s string, msg []byte, off int) (int, error) { | ||||
| 	txtTmp := make([]byte, 256*4+1) | ||||
| 	off, err := packOctetString(s, msg, off, txtTmp) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackDataNsec(msg []byte, off int) ([]uint16, int, error) { | ||||
| 	var nsec []uint16 | ||||
| 	length, window, lastwindow := 0, 0, -1 | ||||
| 	for off < len(msg) { | ||||
| 		if off+2 > len(msg) { | ||||
| 			return nsec, len(msg), &Error{err: "overflow unpacking nsecx"} | ||||
| 		} | ||||
| 		window = int(msg[off]) | ||||
| 		length = int(msg[off+1]) | ||||
| 		off += 2 | ||||
| 		if window <= lastwindow { | ||||
| 			// RFC 4034: Blocks are present in the NSEC RR RDATA in | ||||
| 			// increasing numerical order. | ||||
| 			return nsec, len(msg), &Error{err: "out of order NSEC block"} | ||||
| 		} | ||||
| 		if length == 0 { | ||||
| 			// RFC 4034: Blocks with no types present MUST NOT be included. | ||||
| 			return nsec, len(msg), &Error{err: "empty NSEC block"} | ||||
| 		} | ||||
| 		if length > 32 { | ||||
| 			return nsec, len(msg), &Error{err: "NSEC block too long"} | ||||
| 		} | ||||
| 		if off+length > len(msg) { | ||||
| 			return nsec, len(msg), &Error{err: "overflowing NSEC block"} | ||||
| 		} | ||||
| 
 | ||||
| 		// Walk the bytes in the window and extract the type bits | ||||
| 		for j, b := range msg[off : off+length] { | ||||
| 			// Check the bits one by one, and set the type | ||||
| 			if b&0x80 == 0x80 { | ||||
| 				nsec = append(nsec, uint16(window*256+j*8+0)) | ||||
| 			} | ||||
| 			if b&0x40 == 0x40 { | ||||
| 				nsec = append(nsec, uint16(window*256+j*8+1)) | ||||
| 			} | ||||
| 			if b&0x20 == 0x20 { | ||||
| 				nsec = append(nsec, uint16(window*256+j*8+2)) | ||||
| 			} | ||||
| 			if b&0x10 == 0x10 { | ||||
| 				nsec = append(nsec, uint16(window*256+j*8+3)) | ||||
| 			} | ||||
| 			if b&0x8 == 0x8 { | ||||
| 				nsec = append(nsec, uint16(window*256+j*8+4)) | ||||
| 			} | ||||
| 			if b&0x4 == 0x4 { | ||||
| 				nsec = append(nsec, uint16(window*256+j*8+5)) | ||||
| 			} | ||||
| 			if b&0x2 == 0x2 { | ||||
| 				nsec = append(nsec, uint16(window*256+j*8+6)) | ||||
| 			} | ||||
| 			if b&0x1 == 0x1 { | ||||
| 				nsec = append(nsec, uint16(window*256+j*8+7)) | ||||
| 			} | ||||
| 		} | ||||
| 		off += length | ||||
| 		lastwindow = window | ||||
| 	} | ||||
| 	return nsec, off, nil | ||||
| } | ||||
| 
 | ||||
| // typeBitMapLen is a helper function which computes the "maximum" length of | ||||
| // a the NSEC Type BitMap field. | ||||
| func typeBitMapLen(bitmap []uint16) int { | ||||
| 	var l int | ||||
| 	var lastwindow, lastlength uint16 | ||||
| 	for _, t := range bitmap { | ||||
| 		window := t / 256 | ||||
| 		length := (t-window*256)/8 + 1 | ||||
| 		if window > lastwindow && lastlength != 0 { // New window, jump to the new offset | ||||
| 			l += int(lastlength) + 2 | ||||
| 			lastlength = 0 | ||||
| 		} | ||||
| 		if window < lastwindow || length < lastlength { | ||||
| 			// packDataNsec would return Error{err: "nsec bits out of order"} here, but | ||||
| 			// when computing the length, we want do be liberal. | ||||
| 			continue | ||||
| 		} | ||||
| 		lastwindow, lastlength = window, length | ||||
| 	} | ||||
| 	l += int(lastlength) + 2 | ||||
| 	return l | ||||
| } | ||||
| 
 | ||||
| func packDataNsec(bitmap []uint16, msg []byte, off int) (int, error) { | ||||
| 	if len(bitmap) == 0 { | ||||
| 		return off, nil | ||||
| 	} | ||||
| 	if off > len(msg) { | ||||
| 		return off, &Error{err: "overflow packing nsec"} | ||||
| 	} | ||||
| 	toZero := msg[off:] | ||||
| 	if maxLen := typeBitMapLen(bitmap); maxLen < len(toZero) { | ||||
| 		toZero = toZero[:maxLen] | ||||
| 	} | ||||
| 	for i := range toZero { | ||||
| 		toZero[i] = 0 | ||||
| 	} | ||||
| 	var lastwindow, lastlength uint16 | ||||
| 	for _, t := range bitmap { | ||||
| 		window := t / 256 | ||||
| 		length := (t-window*256)/8 + 1 | ||||
| 		if window > lastwindow && lastlength != 0 { // New window, jump to the new offset | ||||
| 			off += int(lastlength) + 2 | ||||
| 			lastlength = 0 | ||||
| 		} | ||||
| 		if window < lastwindow || length < lastlength { | ||||
| 			return len(msg), &Error{err: "nsec bits out of order"} | ||||
| 		} | ||||
| 		if off+2+int(length) > len(msg) { | ||||
| 			return len(msg), &Error{err: "overflow packing nsec"} | ||||
| 		} | ||||
| 		// Setting the window # | ||||
| 		msg[off] = byte(window) | ||||
| 		// Setting the octets length | ||||
| 		msg[off+1] = byte(length) | ||||
| 		// Setting the bit value for the type in the right octet | ||||
| 		msg[off+1+int(length)] |= byte(1 << (7 - t%8)) | ||||
| 		lastwindow, lastlength = window, length | ||||
| 	} | ||||
| 	off += int(lastlength) + 2 | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackDataSVCB(msg []byte, off int) ([]SVCBKeyValue, int, error) { | ||||
| 	var xs []SVCBKeyValue | ||||
| 	var code uint16 | ||||
| 	var length uint16 | ||||
| 	var err error | ||||
| 	for off < len(msg) { | ||||
| 		code, off, err = unpackUint16(msg, off) | ||||
| 		if err != nil { | ||||
| 			return nil, len(msg), &Error{err: "overflow unpacking SVCB"} | ||||
| 		} | ||||
| 		length, off, err = unpackUint16(msg, off) | ||||
| 		if err != nil || off+int(length) > len(msg) { | ||||
| 			return nil, len(msg), &Error{err: "overflow unpacking SVCB"} | ||||
| 		} | ||||
| 		e := makeSVCBKeyValue(SVCBKey(code)) | ||||
| 		if e == nil { | ||||
| 			return nil, len(msg), &Error{err: "bad SVCB key"} | ||||
| 		} | ||||
| 		if err := e.unpack(msg[off : off+int(length)]); err != nil { | ||||
| 			return nil, len(msg), err | ||||
| 		} | ||||
| 		if len(xs) > 0 && e.Key() <= xs[len(xs)-1].Key() { | ||||
| 			return nil, len(msg), &Error{err: "SVCB keys not in strictly increasing order"} | ||||
| 		} | ||||
| 		xs = append(xs, e) | ||||
| 		off += int(length) | ||||
| 	} | ||||
| 	return xs, off, nil | ||||
| } | ||||
| 
 | ||||
| func packDataSVCB(pairs []SVCBKeyValue, msg []byte, off int) (int, error) { | ||||
| 	pairs = append([]SVCBKeyValue(nil), pairs...) | ||||
| 	sort.Slice(pairs, func(i, j int) bool { | ||||
| 		return pairs[i].Key() < pairs[j].Key() | ||||
| 	}) | ||||
| 	prev := svcb_RESERVED | ||||
| 	for _, el := range pairs { | ||||
| 		if el.Key() == prev { | ||||
| 			return len(msg), &Error{err: "repeated SVCB keys are not allowed"} | ||||
| 		} | ||||
| 		prev = el.Key() | ||||
| 		packed, err := el.pack() | ||||
| 		if err != nil { | ||||
| 			return len(msg), err | ||||
| 		} | ||||
| 		off, err = packUint16(uint16(el.Key()), msg, off) | ||||
| 		if err != nil { | ||||
| 			return len(msg), &Error{err: "overflow packing SVCB"} | ||||
| 		} | ||||
| 		off, err = packUint16(uint16(len(packed)), msg, off) | ||||
| 		if err != nil || off+len(packed) > len(msg) { | ||||
| 			return len(msg), &Error{err: "overflow packing SVCB"} | ||||
| 		} | ||||
| 		copy(msg[off:off+len(packed)], packed) | ||||
| 		off += len(packed) | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackDataDomainNames(msg []byte, off, end int) ([]string, int, error) { | ||||
| 	var ( | ||||
| 		servers []string | ||||
| 		s       string | ||||
| 		err     error | ||||
| 	) | ||||
| 	if end > len(msg) { | ||||
| 		return nil, len(msg), &Error{err: "overflow unpacking domain names"} | ||||
| 	} | ||||
| 	for off < end { | ||||
| 		s, off, err = UnpackDomainName(msg, off) | ||||
| 		if err != nil { | ||||
| 			return servers, len(msg), err | ||||
| 		} | ||||
| 		servers = append(servers, s) | ||||
| 	} | ||||
| 	return servers, off, nil | ||||
| } | ||||
| 
 | ||||
| func packDataDomainNames(names []string, msg []byte, off int, compression compressionMap, compress bool) (int, error) { | ||||
| 	var err error | ||||
| 	for _, name := range names { | ||||
| 		off, err = packDomainName(name, msg, off, compression, compress) | ||||
| 		if err != nil { | ||||
| 			return len(msg), err | ||||
| 		} | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func packDataApl(data []APLPrefix, msg []byte, off int) (int, error) { | ||||
| 	var err error | ||||
| 	for i := range data { | ||||
| 		off, err = packDataAplPrefix(&data[i], msg, off) | ||||
| 		if err != nil { | ||||
| 			return len(msg), err | ||||
| 		} | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func packDataAplPrefix(p *APLPrefix, msg []byte, off int) (int, error) { | ||||
| 	if len(p.Network.IP) != len(p.Network.Mask) { | ||||
| 		return len(msg), &Error{err: "address and mask lengths don't match"} | ||||
| 	} | ||||
| 
 | ||||
| 	var err error | ||||
| 	prefix, _ := p.Network.Mask.Size() | ||||
| 	addr := p.Network.IP.Mask(p.Network.Mask)[:(prefix+7)/8] | ||||
| 
 | ||||
| 	switch len(p.Network.IP) { | ||||
| 	case net.IPv4len: | ||||
| 		off, err = packUint16(1, msg, off) | ||||
| 	case net.IPv6len: | ||||
| 		off, err = packUint16(2, msg, off) | ||||
| 	default: | ||||
| 		err = &Error{err: "unrecognized address family"} | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 
 | ||||
| 	off, err = packUint8(uint8(prefix), msg, off) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 
 | ||||
| 	var n uint8 | ||||
| 	if p.Negation { | ||||
| 		n = 0x80 | ||||
| 	} | ||||
| 
 | ||||
| 	// trim trailing zero bytes as specified in RFC3123 Sections 4.1 and 4.2. | ||||
| 	i := len(addr) - 1 | ||||
| 	for ; i >= 0 && addr[i] == 0; i-- { | ||||
| 	} | ||||
| 	addr = addr[:i+1] | ||||
| 
 | ||||
| 	adflen := uint8(len(addr)) & 0x7f | ||||
| 	off, err = packUint8(n|adflen, msg, off) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 
 | ||||
| 	if off+len(addr) > len(msg) { | ||||
| 		return len(msg), &Error{err: "overflow packing APL prefix"} | ||||
| 	} | ||||
| 	off += copy(msg[off:], addr) | ||||
| 
 | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackDataApl(msg []byte, off int) ([]APLPrefix, int, error) { | ||||
| 	var result []APLPrefix | ||||
| 	for off < len(msg) { | ||||
| 		prefix, end, err := unpackDataAplPrefix(msg, off) | ||||
| 		if err != nil { | ||||
| 			return nil, len(msg), err | ||||
| 		} | ||||
| 		off = end | ||||
| 		result = append(result, prefix) | ||||
| 	} | ||||
| 	return result, off, nil | ||||
| } | ||||
| 
 | ||||
| func unpackDataAplPrefix(msg []byte, off int) (APLPrefix, int, error) { | ||||
| 	family, off, err := unpackUint16(msg, off) | ||||
| 	if err != nil { | ||||
| 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"} | ||||
| 	} | ||||
| 	prefix, off, err := unpackUint8(msg, off) | ||||
| 	if err != nil { | ||||
| 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"} | ||||
| 	} | ||||
| 	nlen, off, err := unpackUint8(msg, off) | ||||
| 	if err != nil { | ||||
| 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL prefix"} | ||||
| 	} | ||||
| 
 | ||||
| 	var ip []byte | ||||
| 	switch family { | ||||
| 	case 1: | ||||
| 		ip = make([]byte, net.IPv4len) | ||||
| 	case 2: | ||||
| 		ip = make([]byte, net.IPv6len) | ||||
| 	default: | ||||
| 		return APLPrefix{}, len(msg), &Error{err: "unrecognized APL address family"} | ||||
| 	} | ||||
| 	if int(prefix) > 8*len(ip) { | ||||
| 		return APLPrefix{}, len(msg), &Error{err: "APL prefix too long"} | ||||
| 	} | ||||
| 	afdlen := int(nlen & 0x7f) | ||||
| 	if afdlen > len(ip) { | ||||
| 		return APLPrefix{}, len(msg), &Error{err: "APL length too long"} | ||||
| 	} | ||||
| 	if off+afdlen > len(msg) { | ||||
| 		return APLPrefix{}, len(msg), &Error{err: "overflow unpacking APL address"} | ||||
| 	} | ||||
| 
 | ||||
| 	// Address MUST NOT contain trailing zero bytes per RFC3123 Sections 4.1 and 4.2. | ||||
| 	off += copy(ip, msg[off:off+afdlen]) | ||||
| 	if afdlen > 0 { | ||||
| 		last := ip[afdlen-1] | ||||
| 		if last == 0 { | ||||
| 			return APLPrefix{}, len(msg), &Error{err: "extra APL address bits"} | ||||
| 		} | ||||
| 	} | ||||
| 	ipnet := net.IPNet{ | ||||
| 		IP:   ip, | ||||
| 		Mask: net.CIDRMask(int(prefix), 8*len(ip)), | ||||
| 	} | ||||
| 
 | ||||
| 	return APLPrefix{ | ||||
| 		Negation: (nlen & 0x80) != 0, | ||||
| 		Network:  ipnet, | ||||
| 	}, off, nil | ||||
| } | ||||
							
								
								
									
										117
									
								
								vendor/github.com/miekg/dns/msg_truncate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								vendor/github.com/miekg/dns/msg_truncate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,117 @@ | |||
| package dns | ||||
| 
 | ||||
| // Truncate ensures the reply message will fit into the requested buffer | ||||
| // size by removing records that exceed the requested size. | ||||
| // | ||||
| // It will first check if the reply fits without compression and then with | ||||
| // compression. If it won't fit with compression, Truncate then walks the | ||||
| // record adding as many records as possible without exceeding the | ||||
| // requested buffer size. | ||||
| // | ||||
| // If the message fits within the requested size without compression, | ||||
| // Truncate will set the message's Compress attribute to false. It is | ||||
| // the caller's responsibility to set it back to true if they wish to | ||||
| // compress the payload regardless of size. | ||||
| // | ||||
| // The TC bit will be set if any records were excluded from the message. | ||||
| // If the TC bit is already set on the message it will be retained. | ||||
| // TC indicates that the client should retry over TCP. | ||||
| // | ||||
| // According to RFC 2181, the TC bit should only be set if not all of the | ||||
| // "required" RRs can be included in the response. Unfortunately, we have | ||||
| // no way of knowing which RRs are required so we set the TC bit if any RR | ||||
| // had to be omitted from the response. | ||||
| // | ||||
| // The appropriate buffer size can be retrieved from the requests OPT | ||||
| // record, if present, and is transport specific otherwise. dns.MinMsgSize | ||||
| // should be used for UDP requests without an OPT record, and | ||||
| // dns.MaxMsgSize for TCP requests without an OPT record. | ||||
| func (dns *Msg) Truncate(size int) { | ||||
| 	if dns.IsTsig() != nil { | ||||
| 		// To simplify this implementation, we don't perform | ||||
| 		// truncation on responses with a TSIG record. | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// RFC 6891 mandates that the payload size in an OPT record | ||||
| 	// less than 512 (MinMsgSize) bytes must be treated as equal to 512 bytes. | ||||
| 	// | ||||
| 	// For ease of use, we impose that restriction here. | ||||
| 	if size < MinMsgSize { | ||||
| 		size = MinMsgSize | ||||
| 	} | ||||
| 
 | ||||
| 	l := msgLenWithCompressionMap(dns, nil) // uncompressed length | ||||
| 	if l <= size { | ||||
| 		// Don't waste effort compressing this message. | ||||
| 		dns.Compress = false | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	dns.Compress = true | ||||
| 
 | ||||
| 	edns0 := dns.popEdns0() | ||||
| 	if edns0 != nil { | ||||
| 		// Account for the OPT record that gets added at the end, | ||||
| 		// by subtracting that length from our budget. | ||||
| 		// | ||||
| 		// The EDNS(0) OPT record must have the root domain and | ||||
| 		// it's length is thus unaffected by compression. | ||||
| 		size -= Len(edns0) | ||||
| 	} | ||||
| 
 | ||||
| 	compression := make(map[string]struct{}) | ||||
| 
 | ||||
| 	l = headerSize | ||||
| 	for _, r := range dns.Question { | ||||
| 		l += r.len(l, compression) | ||||
| 	} | ||||
| 
 | ||||
| 	var numAnswer int | ||||
| 	if l < size { | ||||
| 		l, numAnswer = truncateLoop(dns.Answer, size, l, compression) | ||||
| 	} | ||||
| 
 | ||||
| 	var numNS int | ||||
| 	if l < size { | ||||
| 		l, numNS = truncateLoop(dns.Ns, size, l, compression) | ||||
| 	} | ||||
| 
 | ||||
| 	var numExtra int | ||||
| 	if l < size { | ||||
| 		_, numExtra = truncateLoop(dns.Extra, size, l, compression) | ||||
| 	} | ||||
| 
 | ||||
| 	// See the function documentation for when we set this. | ||||
| 	dns.Truncated = dns.Truncated || len(dns.Answer) > numAnswer || | ||||
| 		len(dns.Ns) > numNS || len(dns.Extra) > numExtra | ||||
| 
 | ||||
| 	dns.Answer = dns.Answer[:numAnswer] | ||||
| 	dns.Ns = dns.Ns[:numNS] | ||||
| 	dns.Extra = dns.Extra[:numExtra] | ||||
| 
 | ||||
| 	if edns0 != nil { | ||||
| 		// Add the OPT record back onto the additional section. | ||||
| 		dns.Extra = append(dns.Extra, edns0) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func truncateLoop(rrs []RR, size, l int, compression map[string]struct{}) (int, int) { | ||||
| 	for i, r := range rrs { | ||||
| 		if r == nil { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		l += r.len(l, compression) | ||||
| 		if l > size { | ||||
| 			// Return size, rather than l prior to this record, | ||||
| 			// to prevent any further records being added. | ||||
| 			return size, i | ||||
| 		} | ||||
| 		if l == size { | ||||
| 			return l, i + 1 | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return l, len(rrs) | ||||
| } | ||||
							
								
								
									
										95
									
								
								vendor/github.com/miekg/dns/nsecx.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								vendor/github.com/miekg/dns/nsecx.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,95 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/sha1" | ||||
| 	"encoding/hex" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // HashName hashes a string (label) according to RFC 5155. It returns the hashed string in uppercase. | ||||
| func HashName(label string, ha uint8, iter uint16, salt string) string { | ||||
| 	if ha != SHA1 { | ||||
| 		return "" | ||||
| 	} | ||||
| 
 | ||||
| 	wireSalt := make([]byte, hex.DecodedLen(len(salt))) | ||||
| 	n, err := packStringHex(salt, wireSalt, 0) | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	wireSalt = wireSalt[:n] | ||||
| 
 | ||||
| 	name := make([]byte, 255) | ||||
| 	off, err := PackDomainName(strings.ToLower(label), name, 0, nil, false) | ||||
| 	if err != nil { | ||||
| 		return "" | ||||
| 	} | ||||
| 	name = name[:off] | ||||
| 
 | ||||
| 	s := sha1.New() | ||||
| 	// k = 0 | ||||
| 	s.Write(name) | ||||
| 	s.Write(wireSalt) | ||||
| 	nsec3 := s.Sum(nil) | ||||
| 
 | ||||
| 	// k > 0 | ||||
| 	for k := uint16(0); k < iter; k++ { | ||||
| 		s.Reset() | ||||
| 		s.Write(nsec3) | ||||
| 		s.Write(wireSalt) | ||||
| 		nsec3 = s.Sum(nsec3[:0]) | ||||
| 	} | ||||
| 
 | ||||
| 	return toBase32(nsec3) | ||||
| } | ||||
| 
 | ||||
| // Cover returns true if a name is covered by the NSEC3 record. | ||||
| func (rr *NSEC3) Cover(name string) bool { | ||||
| 	nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt) | ||||
| 	owner := strings.ToUpper(rr.Hdr.Name) | ||||
| 	labelIndices := Split(owner) | ||||
| 	if len(labelIndices) < 2 { | ||||
| 		return false | ||||
| 	} | ||||
| 	ownerHash := owner[:labelIndices[1]-1] | ||||
| 	ownerZone := owner[labelIndices[1]:] | ||||
| 	if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	nextHash := rr.NextDomain | ||||
| 
 | ||||
| 	// if empty interval found, try cover wildcard hashes so nameHash shouldn't match with ownerHash | ||||
| 	if ownerHash == nextHash && nameHash != ownerHash { // empty interval | ||||
| 		return true | ||||
| 	} | ||||
| 	if ownerHash > nextHash { // end of zone | ||||
| 		if nameHash > ownerHash { // covered since there is nothing after ownerHash | ||||
| 			return true | ||||
| 		} | ||||
| 		return nameHash < nextHash // if nameHash is before beginning of zone it is covered | ||||
| 	} | ||||
| 	if nameHash < ownerHash { // nameHash is before ownerHash, not covered | ||||
| 		return false | ||||
| 	} | ||||
| 	return nameHash < nextHash // if nameHash is before nextHash is it covered (between ownerHash and nextHash) | ||||
| } | ||||
| 
 | ||||
| // Match returns true if a name matches the NSEC3 record | ||||
| func (rr *NSEC3) Match(name string) bool { | ||||
| 	nameHash := HashName(name, rr.Hash, rr.Iterations, rr.Salt) | ||||
| 	owner := strings.ToUpper(rr.Hdr.Name) | ||||
| 	labelIndices := Split(owner) | ||||
| 	if len(labelIndices) < 2 { | ||||
| 		return false | ||||
| 	} | ||||
| 	ownerHash := owner[:labelIndices[1]-1] | ||||
| 	ownerZone := owner[labelIndices[1]:] | ||||
| 	if !IsSubDomain(ownerZone, strings.ToUpper(name)) { // name is outside owner zone | ||||
| 		return false | ||||
| 	} | ||||
| 	if ownerHash == nameHash { | ||||
| 		return true | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
							
								
								
									
										113
									
								
								vendor/github.com/miekg/dns/privaterr.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								vendor/github.com/miekg/dns/privaterr.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,113 @@ | |||
| package dns | ||||
| 
 | ||||
| import "strings" | ||||
| 
 | ||||
| // PrivateRdata is an interface used for implementing "Private Use" RR types, see | ||||
| // RFC 6895. This allows one to experiment with new RR types, without requesting an | ||||
| // official type code. Also see dns.PrivateHandle and dns.PrivateHandleRemove. | ||||
| type PrivateRdata interface { | ||||
| 	// String returns the text presentation of the Rdata of the Private RR. | ||||
| 	String() string | ||||
| 	// Parse parses the Rdata of the private RR. | ||||
| 	Parse([]string) error | ||||
| 	// Pack is used when packing a private RR into a buffer. | ||||
| 	Pack([]byte) (int, error) | ||||
| 	// Unpack is used when unpacking a private RR from a buffer. | ||||
| 	Unpack([]byte) (int, error) | ||||
| 	// Copy copies the Rdata into the PrivateRdata argument. | ||||
| 	Copy(PrivateRdata) error | ||||
| 	// Len returns the length in octets of the Rdata. | ||||
| 	Len() int | ||||
| } | ||||
| 
 | ||||
| // PrivateRR represents an RR that uses a PrivateRdata user-defined type. | ||||
| // It mocks normal RRs and implements dns.RR interface. | ||||
| type PrivateRR struct { | ||||
| 	Hdr  RR_Header | ||||
| 	Data PrivateRdata | ||||
| 
 | ||||
| 	generator func() PrivateRdata // for copy | ||||
| } | ||||
| 
 | ||||
| // Header return the RR header of r. | ||||
| func (r *PrivateRR) Header() *RR_Header { return &r.Hdr } | ||||
| 
 | ||||
| func (r *PrivateRR) String() string { return r.Hdr.String() + r.Data.String() } | ||||
| 
 | ||||
| // Private len and copy parts to satisfy RR interface. | ||||
| func (r *PrivateRR) len(off int, compression map[string]struct{}) int { | ||||
| 	l := r.Hdr.len(off, compression) | ||||
| 	l += r.Data.Len() | ||||
| 	return l | ||||
| } | ||||
| 
 | ||||
| func (r *PrivateRR) copy() RR { | ||||
| 	// make new RR like this: | ||||
| 	rr := &PrivateRR{r.Hdr, r.generator(), r.generator} | ||||
| 
 | ||||
| 	if err := r.Data.Copy(rr.Data); err != nil { | ||||
| 		panic("dns: got value that could not be used to copy Private rdata: " + err.Error()) | ||||
| 	} | ||||
| 
 | ||||
| 	return rr | ||||
| } | ||||
| 
 | ||||
| func (r *PrivateRR) pack(msg []byte, off int, compression compressionMap, compress bool) (int, error) { | ||||
| 	n, err := r.Data.Pack(msg[off:]) | ||||
| 	if err != nil { | ||||
| 		return len(msg), err | ||||
| 	} | ||||
| 	off += n | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func (r *PrivateRR) unpack(msg []byte, off int) (int, error) { | ||||
| 	off1, err := r.Data.Unpack(msg[off:]) | ||||
| 	off += off1 | ||||
| 	return off, err | ||||
| } | ||||
| 
 | ||||
| func (r *PrivateRR) parse(c *zlexer, origin string) *ParseError { | ||||
| 	var l lex | ||||
| 	text := make([]string, 0, 2) // could be 0..N elements, median is probably 1 | ||||
| Fetch: | ||||
| 	for { | ||||
| 		// TODO(miek): we could also be returning _QUOTE, this might or might not | ||||
| 		// be an issue (basically parsing TXT becomes hard) | ||||
| 		switch l, _ = c.Next(); l.value { | ||||
| 		case zNewline, zEOF: | ||||
| 			break Fetch | ||||
| 		case zString: | ||||
| 			text = append(text, l.token) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	err := r.Data.Parse(text) | ||||
| 	if err != nil { | ||||
| 		return &ParseError{"", err.Error(), l} | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (r *PrivateRR) isDuplicate(r2 RR) bool { return false } | ||||
| 
 | ||||
| // PrivateHandle registers a private resource record type. It requires | ||||
| // string and numeric representation of private RR type and generator function as argument. | ||||
| func PrivateHandle(rtypestr string, rtype uint16, generator func() PrivateRdata) { | ||||
| 	rtypestr = strings.ToUpper(rtypestr) | ||||
| 
 | ||||
| 	TypeToRR[rtype] = func() RR { return &PrivateRR{RR_Header{}, generator(), generator} } | ||||
| 	TypeToString[rtype] = rtypestr | ||||
| 	StringToType[rtypestr] = rtype | ||||
| } | ||||
| 
 | ||||
| // PrivateHandleRemove removes definitions required to support private RR type. | ||||
| func PrivateHandleRemove(rtype uint16) { | ||||
| 	rtypestr, ok := TypeToString[rtype] | ||||
| 	if ok { | ||||
| 		delete(TypeToRR, rtype) | ||||
| 		delete(TypeToString, rtype) | ||||
| 		delete(StringToType, rtypestr) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										52
									
								
								vendor/github.com/miekg/dns/reverse.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								vendor/github.com/miekg/dns/reverse.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | |||
| package dns | ||||
| 
 | ||||
| // StringToType is the reverse of TypeToString, needed for string parsing. | ||||
| var StringToType = reverseInt16(TypeToString) | ||||
| 
 | ||||
| // StringToClass is the reverse of ClassToString, needed for string parsing. | ||||
| var StringToClass = reverseInt16(ClassToString) | ||||
| 
 | ||||
| // StringToOpcode is a map of opcodes to strings. | ||||
| var StringToOpcode = reverseInt(OpcodeToString) | ||||
| 
 | ||||
| // StringToRcode is a map of rcodes to strings. | ||||
| var StringToRcode = reverseInt(RcodeToString) | ||||
| 
 | ||||
| func init() { | ||||
| 	// Preserve previous NOTIMP typo, see github.com/miekg/dns/issues/733. | ||||
| 	StringToRcode["NOTIMPL"] = RcodeNotImplemented | ||||
| } | ||||
| 
 | ||||
| // StringToAlgorithm is the reverse of AlgorithmToString. | ||||
| var StringToAlgorithm = reverseInt8(AlgorithmToString) | ||||
| 
 | ||||
| // StringToHash is a map of names to hash IDs. | ||||
| var StringToHash = reverseInt8(HashToString) | ||||
| 
 | ||||
| // StringToCertType is the reverseof CertTypeToString. | ||||
| var StringToCertType = reverseInt16(CertTypeToString) | ||||
| 
 | ||||
| // Reverse a map | ||||
| func reverseInt8(m map[uint8]string) map[string]uint8 { | ||||
| 	n := make(map[string]uint8, len(m)) | ||||
| 	for u, s := range m { | ||||
| 		n[s] = u | ||||
| 	} | ||||
| 	return n | ||||
| } | ||||
| 
 | ||||
| func reverseInt16(m map[uint16]string) map[string]uint16 { | ||||
| 	n := make(map[string]uint16, len(m)) | ||||
| 	for u, s := range m { | ||||
| 		n[s] = u | ||||
| 	} | ||||
| 	return n | ||||
| } | ||||
| 
 | ||||
| func reverseInt(m map[int]string) map[string]int { | ||||
| 	n := make(map[string]int, len(m)) | ||||
| 	for u, s := range m { | ||||
| 		n[s] = u | ||||
| 	} | ||||
| 	return n | ||||
| } | ||||
							
								
								
									
										86
									
								
								vendor/github.com/miekg/dns/sanitize.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								vendor/github.com/miekg/dns/sanitize.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,86 @@ | |||
| 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 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) | ||||
| 	} | ||||
| 	// Save the keys, so we don't have to call normalizedString twice. | ||||
| 	keys := make([]*string, 0, len(rrs)) | ||||
| 
 | ||||
| 	for _, r := range rrs { | ||||
| 		key := normalizedString(r) | ||||
| 		keys = append(keys, &key) | ||||
| 		if mr, ok := m[key]; ok { | ||||
| 			// Shortest TTL wins. | ||||
| 			rh, mrh := r.Header(), mr.Header() | ||||
| 			if mrh.Ttl > rh.Ttl { | ||||
| 				mrh.Ttl = rh.Ttl | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		m[key] = r | ||||
| 	} | ||||
| 	// If the length of the result map equals the amount of RRs we got, | ||||
| 	// it means they were all different. We can then just return the original rrset. | ||||
| 	if len(m) == len(rrs) { | ||||
| 		return rrs | ||||
| 	} | ||||
| 
 | ||||
| 	j := 0 | ||||
| 	for i, r := range rrs { | ||||
| 		// If keys[i] lives in the map, we should copy and remove it. | ||||
| 		if _, ok := m[*keys[i]]; ok { | ||||
| 			delete(m, *keys[i]) | ||||
| 			rrs[j] = r | ||||
| 			j++ | ||||
| 		} | ||||
| 
 | ||||
| 		if len(m) == 0 { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return rrs[:j] | ||||
| } | ||||
| 
 | ||||
| // normalizedString returns a normalized string from r. The TTL | ||||
| // is removed and the domain name is lowercased. We go from this: | ||||
| // DomainName<TAB>TTL<TAB>CLASS<TAB>TYPE<TAB>RDATA to: | ||||
| // lowercasename<TAB>CLASS<TAB>TYPE... | ||||
| func normalizedString(r RR) string { | ||||
| 	// A string Go DNS makes has: domainname<TAB>TTL<TAB>... | ||||
| 	b := []byte(r.String()) | ||||
| 
 | ||||
| 	// find the first non-escaped tab, then another, so we capture where the TTL lives. | ||||
| 	esc := false | ||||
| 	ttlStart, ttlEnd := 0, 0 | ||||
| 	for i := 0; i < len(b) && ttlEnd == 0; i++ { | ||||
| 		switch { | ||||
| 		case b[i] == '\\': | ||||
| 			esc = !esc | ||||
| 		case b[i] == '\t' && !esc: | ||||
| 			if ttlStart == 0 { | ||||
| 				ttlStart = i | ||||
| 				continue | ||||
| 			} | ||||
| 			if ttlEnd == 0 { | ||||
| 				ttlEnd = i | ||||
| 			} | ||||
| 		case b[i] >= 'A' && b[i] <= 'Z' && !esc: | ||||
| 			b[i] += 32 | ||||
| 		default: | ||||
| 			esc = false | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// remove TTL. | ||||
| 	copy(b[ttlStart:], b[ttlEnd:]) | ||||
| 	cut := ttlEnd - ttlStart | ||||
| 	return string(b[:len(b)-cut]) | ||||
| } | ||||
							
								
								
									
										1368
									
								
								vendor/github.com/miekg/dns/scan.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1368
									
								
								vendor/github.com/miekg/dns/scan.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1778
									
								
								vendor/github.com/miekg/dns/scan_rr.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1778
									
								
								vendor/github.com/miekg/dns/scan_rr.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										122
									
								
								vendor/github.com/miekg/dns/serve_mux.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								vendor/github.com/miekg/dns/serve_mux.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,122 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"sync" | ||||
| ) | ||||
| 
 | ||||
| // ServeMux is an DNS request multiplexer. It matches the zone name of | ||||
| // each incoming request against a list of registered patterns add calls | ||||
| // the handler for the pattern that most closely matches the zone name. | ||||
| // | ||||
| // ServeMux is DNSSEC aware, meaning that queries for the DS record are | ||||
| // redirected to the parent zone (if that is also registered), otherwise | ||||
| // the child gets the query. | ||||
| // | ||||
| // ServeMux is also safe for concurrent access from multiple goroutines. | ||||
| // | ||||
| // The zero ServeMux is empty and ready for use. | ||||
| type ServeMux struct { | ||||
| 	z map[string]Handler | ||||
| 	m sync.RWMutex | ||||
| } | ||||
| 
 | ||||
| // NewServeMux allocates and returns a new ServeMux. | ||||
| func NewServeMux() *ServeMux { | ||||
| 	return new(ServeMux) | ||||
| } | ||||
| 
 | ||||
| // DefaultServeMux is the default ServeMux used by Serve. | ||||
| var DefaultServeMux = NewServeMux() | ||||
| 
 | ||||
| func (mux *ServeMux) match(q string, t uint16) Handler { | ||||
| 	mux.m.RLock() | ||||
| 	defer mux.m.RUnlock() | ||||
| 	if mux.z == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	q = CanonicalName(q) | ||||
| 
 | ||||
| 	var handler Handler | ||||
| 	for off, end := 0, false; !end; off, end = NextLabel(q, off) { | ||||
| 		if h, ok := mux.z[q[off:]]; ok { | ||||
| 			if t != TypeDS { | ||||
| 				return h | ||||
| 			} | ||||
| 			// Continue for DS to see if we have a parent too, if so delegate to the parent | ||||
| 			handler = h | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Wildcard match, if we have found nothing try the root zone as a last resort. | ||||
| 	if h, ok := mux.z["."]; ok { | ||||
| 		return h | ||||
| 	} | ||||
| 
 | ||||
| 	return handler | ||||
| } | ||||
| 
 | ||||
| // Handle adds a handler to the ServeMux for pattern. | ||||
| func (mux *ServeMux) Handle(pattern string, handler Handler) { | ||||
| 	if pattern == "" { | ||||
| 		panic("dns: invalid pattern " + pattern) | ||||
| 	} | ||||
| 	mux.m.Lock() | ||||
| 	if mux.z == nil { | ||||
| 		mux.z = make(map[string]Handler) | ||||
| 	} | ||||
| 	mux.z[CanonicalName(pattern)] = handler | ||||
| 	mux.m.Unlock() | ||||
| } | ||||
| 
 | ||||
| // HandleFunc adds a handler function to the ServeMux for pattern. | ||||
| func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) { | ||||
| 	mux.Handle(pattern, HandlerFunc(handler)) | ||||
| } | ||||
| 
 | ||||
| // HandleRemove deregisters the handler specific for pattern from the ServeMux. | ||||
| func (mux *ServeMux) HandleRemove(pattern string) { | ||||
| 	if pattern == "" { | ||||
| 		panic("dns: invalid pattern " + pattern) | ||||
| 	} | ||||
| 	mux.m.Lock() | ||||
| 	delete(mux.z, CanonicalName(pattern)) | ||||
| 	mux.m.Unlock() | ||||
| } | ||||
| 
 | ||||
| // ServeDNS dispatches the request to the handler whose pattern most | ||||
| // closely matches the request message. | ||||
| // | ||||
| // ServeDNS is DNSSEC aware, meaning that queries for the DS record | ||||
| // are redirected to the parent zone (if that is also registered), | ||||
| // otherwise the child gets the query. | ||||
| // | ||||
| // If no handler is found, or there is no question, a standard REFUSED | ||||
| // message is returned | ||||
| func (mux *ServeMux) ServeDNS(w ResponseWriter, req *Msg) { | ||||
| 	var h Handler | ||||
| 	if len(req.Question) >= 1 { // allow more than one question | ||||
| 		h = mux.match(req.Question[0].Name, req.Question[0].Qtype) | ||||
| 	} | ||||
| 
 | ||||
| 	if h != nil { | ||||
| 		h.ServeDNS(w, req) | ||||
| 	} else { | ||||
| 		handleRefused(w, req) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Handle registers the handler with the given pattern | ||||
| // in the DefaultServeMux. The documentation for | ||||
| // ServeMux explains how patterns are matched. | ||||
| func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) } | ||||
| 
 | ||||
| // HandleRemove deregisters the handle with the given pattern | ||||
| // in the DefaultServeMux. | ||||
| func HandleRemove(pattern string) { DefaultServeMux.HandleRemove(pattern) } | ||||
| 
 | ||||
| // HandleFunc registers the handler function with the given pattern | ||||
| // in the DefaultServeMux. | ||||
| func HandleFunc(pattern string, handler func(ResponseWriter, *Msg)) { | ||||
| 	DefaultServeMux.HandleFunc(pattern, handler) | ||||
| } | ||||
							
								
								
									
										836
									
								
								vendor/github.com/miekg/dns/server.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										836
									
								
								vendor/github.com/miekg/dns/server.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,836 @@ | |||
| // DNS server implementation. | ||||
| 
 | ||||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/tls" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"io" | ||||
| 	"net" | ||||
| 	"strings" | ||||
| 	"sync" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // Default maximum number of TCP queries before we close the socket. | ||||
| const maxTCPQueries = 128 | ||||
| 
 | ||||
| // aLongTimeAgo is a non-zero time, far in the past, used for | ||||
| // immediate cancelation of network operations. | ||||
| var aLongTimeAgo = time.Unix(1, 0) | ||||
| 
 | ||||
| // Handler is implemented by any value that implements ServeDNS. | ||||
| type Handler interface { | ||||
| 	ServeDNS(w ResponseWriter, r *Msg) | ||||
| } | ||||
| 
 | ||||
| // The HandlerFunc type is an adapter to allow the use of | ||||
| // ordinary functions as DNS handlers.  If f is a function | ||||
| // with the appropriate signature, HandlerFunc(f) is a | ||||
| // Handler object that calls f. | ||||
| type HandlerFunc func(ResponseWriter, *Msg) | ||||
| 
 | ||||
| // ServeDNS calls f(w, r). | ||||
| func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg) { | ||||
| 	f(w, r) | ||||
| } | ||||
| 
 | ||||
| // A ResponseWriter interface is used by an DNS handler to | ||||
| // construct an DNS response. | ||||
| type ResponseWriter interface { | ||||
| 	// LocalAddr returns the net.Addr of the server | ||||
| 	LocalAddr() net.Addr | ||||
| 	// RemoteAddr returns the net.Addr of the client that sent the current request. | ||||
| 	RemoteAddr() net.Addr | ||||
| 	// WriteMsg writes a reply back to the client. | ||||
| 	WriteMsg(*Msg) error | ||||
| 	// Write writes a raw buffer back to the client. | ||||
| 	Write([]byte) (int, error) | ||||
| 	// Close closes the connection. | ||||
| 	Close() error | ||||
| 	// TsigStatus returns the status of the Tsig. | ||||
| 	TsigStatus() error | ||||
| 	// TsigTimersOnly sets the tsig timers only boolean. | ||||
| 	TsigTimersOnly(bool) | ||||
| 	// Hijack lets the caller take over the connection. | ||||
| 	// After a call to Hijack(), the DNS package will not do anything with the connection. | ||||
| 	Hijack() | ||||
| } | ||||
| 
 | ||||
| // A ConnectionStater interface is used by a DNS Handler to access TLS connection state | ||||
| // when available. | ||||
| type ConnectionStater interface { | ||||
| 	ConnectionState() *tls.ConnectionState | ||||
| } | ||||
| 
 | ||||
| type response struct { | ||||
| 	closed         bool // connection has been closed | ||||
| 	hijacked       bool // connection has been hijacked by handler | ||||
| 	tsigTimersOnly bool | ||||
| 	tsigStatus     error | ||||
| 	tsigRequestMAC string | ||||
| 	tsigProvider   TsigProvider | ||||
| 	udp            net.PacketConn // i/o connection if UDP was used | ||||
| 	tcp            net.Conn       // i/o connection if TCP was used | ||||
| 	udpSession     *SessionUDP    // oob data to get egress interface right | ||||
| 	pcSession      net.Addr       // address to use when writing to a generic net.PacketConn | ||||
| 	writer         Writer         // writer to output the raw DNS bits | ||||
| } | ||||
| 
 | ||||
| // handleRefused returns a HandlerFunc that returns REFUSED for every request it gets. | ||||
| func handleRefused(w ResponseWriter, r *Msg) { | ||||
| 	m := new(Msg) | ||||
| 	m.SetRcode(r, RcodeRefused) | ||||
| 	w.WriteMsg(m) | ||||
| } | ||||
| 
 | ||||
| // HandleFailed returns a HandlerFunc that returns SERVFAIL for every request it gets. | ||||
| // Deprecated: This function is going away. | ||||
| func HandleFailed(w ResponseWriter, r *Msg) { | ||||
| 	m := new(Msg) | ||||
| 	m.SetRcode(r, RcodeServerFailure) | ||||
| 	// does not matter if this write fails | ||||
| 	w.WriteMsg(m) | ||||
| } | ||||
| 
 | ||||
| // ListenAndServe Starts a server on address and network specified Invoke handler | ||||
| // for incoming queries. | ||||
| func ListenAndServe(addr string, network string, handler Handler) error { | ||||
| 	server := &Server{Addr: addr, Net: network, Handler: handler} | ||||
| 	return server.ListenAndServe() | ||||
| } | ||||
| 
 | ||||
| // ListenAndServeTLS acts like http.ListenAndServeTLS, more information in | ||||
| // http://golang.org/pkg/net/http/#ListenAndServeTLS | ||||
| func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error { | ||||
| 	cert, err := tls.LoadX509KeyPair(certFile, keyFile) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	config := tls.Config{ | ||||
| 		Certificates: []tls.Certificate{cert}, | ||||
| 	} | ||||
| 
 | ||||
| 	server := &Server{ | ||||
| 		Addr:      addr, | ||||
| 		Net:       "tcp-tls", | ||||
| 		TLSConfig: &config, | ||||
| 		Handler:   handler, | ||||
| 	} | ||||
| 
 | ||||
| 	return server.ListenAndServe() | ||||
| } | ||||
| 
 | ||||
| // ActivateAndServe activates a server with a listener from systemd, | ||||
| // l and p should not both be non-nil. | ||||
| // If both l and p are not nil only p will be used. | ||||
| // Invoke handler for incoming queries. | ||||
| func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error { | ||||
| 	server := &Server{Listener: l, PacketConn: p, Handler: handler} | ||||
| 	return server.ActivateAndServe() | ||||
| } | ||||
| 
 | ||||
| // Writer writes raw DNS messages; each call to Write should send an entire message. | ||||
| type Writer interface { | ||||
| 	io.Writer | ||||
| } | ||||
| 
 | ||||
| // Reader reads raw DNS messages; each call to ReadTCP or ReadUDP should return an entire message. | ||||
| type Reader interface { | ||||
| 	// ReadTCP reads a raw message from a TCP connection. Implementations may alter | ||||
| 	// connection properties, for example the read-deadline. | ||||
| 	ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) | ||||
| 	// ReadUDP reads a raw message from a UDP connection. Implementations may alter | ||||
| 	// connection properties, for example the read-deadline. | ||||
| 	ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) | ||||
| } | ||||
| 
 | ||||
| // PacketConnReader is an optional interface that Readers can implement to support using generic net.PacketConns. | ||||
| type PacketConnReader interface { | ||||
| 	Reader | ||||
| 
 | ||||
| 	// ReadPacketConn reads a raw message from a generic net.PacketConn UDP connection. Implementations may | ||||
| 	// alter connection properties, for example the read-deadline. | ||||
| 	ReadPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error) | ||||
| } | ||||
| 
 | ||||
| // defaultReader is an adapter for the Server struct that implements the Reader and | ||||
| // PacketConnReader interfaces using the readTCP, readUDP and readPacketConn funcs | ||||
| // of the embedded Server. | ||||
| type defaultReader struct { | ||||
| 	*Server | ||||
| } | ||||
| 
 | ||||
| var _ PacketConnReader = defaultReader{} | ||||
| 
 | ||||
| func (dr defaultReader) ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error) { | ||||
| 	return dr.readTCP(conn, timeout) | ||||
| } | ||||
| 
 | ||||
| func (dr defaultReader) ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) { | ||||
| 	return dr.readUDP(conn, timeout) | ||||
| } | ||||
| 
 | ||||
| func (dr defaultReader) ReadPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error) { | ||||
| 	return dr.readPacketConn(conn, timeout) | ||||
| } | ||||
| 
 | ||||
| // DecorateReader is a decorator hook for extending or supplanting the functionality of a Reader. | ||||
| // Implementations should never return a nil Reader. | ||||
| // Readers should also implement the optional PacketConnReader interface. | ||||
| // PacketConnReader is required to use a generic net.PacketConn. | ||||
| type DecorateReader func(Reader) Reader | ||||
| 
 | ||||
| // DecorateWriter is a decorator hook for extending or supplanting the functionality of a Writer. | ||||
| // Implementations should never return a nil Writer. | ||||
| type DecorateWriter func(Writer) Writer | ||||
| 
 | ||||
| // A Server defines parameters for running an DNS server. | ||||
| type Server struct { | ||||
| 	// Address to listen on, ":dns" if empty. | ||||
| 	Addr string | ||||
| 	// if "tcp" or "tcp-tls" (DNS over TLS) it will invoke a TCP listener, otherwise an UDP one | ||||
| 	Net string | ||||
| 	// TCP Listener to use, this is to aid in systemd's socket activation. | ||||
| 	Listener net.Listener | ||||
| 	// TLS connection configuration | ||||
| 	TLSConfig *tls.Config | ||||
| 	// UDP "Listener" to use, this is to aid in systemd's socket activation. | ||||
| 	PacketConn net.PacketConn | ||||
| 	// Handler to invoke, dns.DefaultServeMux if nil. | ||||
| 	Handler Handler | ||||
| 	// Default buffer size to use to read incoming UDP messages. If not set | ||||
| 	// it defaults to MinMsgSize (512 B). | ||||
| 	UDPSize int | ||||
| 	// The net.Conn.SetReadTimeout value for new connections, defaults to 2 * time.Second. | ||||
| 	ReadTimeout time.Duration | ||||
| 	// The net.Conn.SetWriteTimeout value for new connections, defaults to 2 * time.Second. | ||||
| 	WriteTimeout time.Duration | ||||
| 	// TCP idle timeout for multiple queries, if nil, defaults to 8 * time.Second (RFC 5966). | ||||
| 	IdleTimeout func() time.Duration | ||||
| 	// An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations. | ||||
| 	TsigProvider TsigProvider | ||||
| 	// 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 | ||||
| 	// If NotifyStartedFunc is set it is called once the server has started listening. | ||||
| 	NotifyStartedFunc func() | ||||
| 	// DecorateReader is optional, allows customization of the process that reads raw DNS messages. | ||||
| 	DecorateReader DecorateReader | ||||
| 	// DecorateWriter is optional, allows customization of the process that writes raw DNS messages. | ||||
| 	DecorateWriter DecorateWriter | ||||
| 	// Maximum number of TCP queries before we close the socket. Default is maxTCPQueries (unlimited if -1). | ||||
| 	MaxTCPQueries int | ||||
| 	// Whether to set the SO_REUSEPORT socket option, allowing multiple listeners to be bound to a single address. | ||||
| 	// It is only supported on go1.11+ and when using ListenAndServe. | ||||
| 	ReusePort bool | ||||
| 	// AcceptMsgFunc will check the incoming message and will reject it early in the process. | ||||
| 	// By default DefaultMsgAcceptFunc will be used. | ||||
| 	MsgAcceptFunc MsgAcceptFunc | ||||
| 
 | ||||
| 	// Shutdown handling | ||||
| 	lock     sync.RWMutex | ||||
| 	started  bool | ||||
| 	shutdown chan struct{} | ||||
| 	conns    map[net.Conn]struct{} | ||||
| 
 | ||||
| 	// A pool for UDP message buffers. | ||||
| 	udpPool sync.Pool | ||||
| } | ||||
| 
 | ||||
| func (srv *Server) tsigProvider() TsigProvider { | ||||
| 	if srv.TsigProvider != nil { | ||||
| 		return srv.TsigProvider | ||||
| 	} | ||||
| 	if srv.TsigSecret != nil { | ||||
| 		return tsigSecretProvider(srv.TsigSecret) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (srv *Server) isStarted() bool { | ||||
| 	srv.lock.RLock() | ||||
| 	started := srv.started | ||||
| 	srv.lock.RUnlock() | ||||
| 	return started | ||||
| } | ||||
| 
 | ||||
| func makeUDPBuffer(size int) func() interface{} { | ||||
| 	return func() interface{} { | ||||
| 		return make([]byte, size) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (srv *Server) init() { | ||||
| 	srv.shutdown = make(chan struct{}) | ||||
| 	srv.conns = make(map[net.Conn]struct{}) | ||||
| 
 | ||||
| 	if srv.UDPSize == 0 { | ||||
| 		srv.UDPSize = MinMsgSize | ||||
| 	} | ||||
| 	if srv.MsgAcceptFunc == nil { | ||||
| 		srv.MsgAcceptFunc = DefaultMsgAcceptFunc | ||||
| 	} | ||||
| 	if srv.Handler == nil { | ||||
| 		srv.Handler = DefaultServeMux | ||||
| 	} | ||||
| 
 | ||||
| 	srv.udpPool.New = makeUDPBuffer(srv.UDPSize) | ||||
| } | ||||
| 
 | ||||
| func unlockOnce(l sync.Locker) func() { | ||||
| 	var once sync.Once | ||||
| 	return func() { once.Do(l.Unlock) } | ||||
| } | ||||
| 
 | ||||
| // ListenAndServe starts a nameserver on the configured address in *Server. | ||||
| func (srv *Server) ListenAndServe() error { | ||||
| 	unlock := unlockOnce(&srv.lock) | ||||
| 	srv.lock.Lock() | ||||
| 	defer unlock() | ||||
| 
 | ||||
| 	if srv.started { | ||||
| 		return &Error{err: "server already started"} | ||||
| 	} | ||||
| 
 | ||||
| 	addr := srv.Addr | ||||
| 	if addr == "" { | ||||
| 		addr = ":domain" | ||||
| 	} | ||||
| 
 | ||||
| 	srv.init() | ||||
| 
 | ||||
| 	switch srv.Net { | ||||
| 	case "tcp", "tcp4", "tcp6": | ||||
| 		l, err := listenTCP(srv.Net, addr, srv.ReusePort) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		srv.Listener = l | ||||
| 		srv.started = true | ||||
| 		unlock() | ||||
| 		return srv.serveTCP(l) | ||||
| 	case "tcp-tls", "tcp4-tls", "tcp6-tls": | ||||
| 		if srv.TLSConfig == nil || (len(srv.TLSConfig.Certificates) == 0 && srv.TLSConfig.GetCertificate == nil) { | ||||
| 			return errors.New("dns: neither Certificates nor GetCertificate set in Config") | ||||
| 		} | ||||
| 		network := strings.TrimSuffix(srv.Net, "-tls") | ||||
| 		l, err := listenTCP(network, addr, srv.ReusePort) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		l = tls.NewListener(l, srv.TLSConfig) | ||||
| 		srv.Listener = l | ||||
| 		srv.started = true | ||||
| 		unlock() | ||||
| 		return srv.serveTCP(l) | ||||
| 	case "udp", "udp4", "udp6": | ||||
| 		l, err := listenUDP(srv.Net, addr, srv.ReusePort) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		u := l.(*net.UDPConn) | ||||
| 		if e := setUDPSocketOptions(u); e != nil { | ||||
| 			u.Close() | ||||
| 			return e | ||||
| 		} | ||||
| 		srv.PacketConn = l | ||||
| 		srv.started = true | ||||
| 		unlock() | ||||
| 		return srv.serveUDP(u) | ||||
| 	} | ||||
| 	return &Error{err: "bad network"} | ||||
| } | ||||
| 
 | ||||
| // ActivateAndServe starts a nameserver with the PacketConn or Listener | ||||
| // configured in *Server. Its main use is to start a server from systemd. | ||||
| func (srv *Server) ActivateAndServe() error { | ||||
| 	unlock := unlockOnce(&srv.lock) | ||||
| 	srv.lock.Lock() | ||||
| 	defer unlock() | ||||
| 
 | ||||
| 	if srv.started { | ||||
| 		return &Error{err: "server already started"} | ||||
| 	} | ||||
| 
 | ||||
| 	srv.init() | ||||
| 
 | ||||
| 	if srv.PacketConn != nil { | ||||
| 		// Check PacketConn interface's type is valid and value | ||||
| 		// is not nil | ||||
| 		if t, ok := srv.PacketConn.(*net.UDPConn); ok && t != nil { | ||||
| 			if e := setUDPSocketOptions(t); e != nil { | ||||
| 				return e | ||||
| 			} | ||||
| 		} | ||||
| 		srv.started = true | ||||
| 		unlock() | ||||
| 		return srv.serveUDP(srv.PacketConn) | ||||
| 	} | ||||
| 	if srv.Listener != nil { | ||||
| 		srv.started = true | ||||
| 		unlock() | ||||
| 		return srv.serveTCP(srv.Listener) | ||||
| 	} | ||||
| 	return &Error{err: "bad listeners"} | ||||
| } | ||||
| 
 | ||||
| // Shutdown shuts down a server. After a call to Shutdown, ListenAndServe and | ||||
| // ActivateAndServe will return. | ||||
| func (srv *Server) Shutdown() error { | ||||
| 	return srv.ShutdownContext(context.Background()) | ||||
| } | ||||
| 
 | ||||
| // ShutdownContext shuts down a server. After a call to ShutdownContext, | ||||
| // ListenAndServe and ActivateAndServe will return. | ||||
| // | ||||
| // A context.Context may be passed to limit how long to wait for connections | ||||
| // to terminate. | ||||
| func (srv *Server) ShutdownContext(ctx context.Context) error { | ||||
| 	srv.lock.Lock() | ||||
| 	if !srv.started { | ||||
| 		srv.lock.Unlock() | ||||
| 		return &Error{err: "server not started"} | ||||
| 	} | ||||
| 
 | ||||
| 	srv.started = false | ||||
| 
 | ||||
| 	if srv.PacketConn != nil { | ||||
| 		srv.PacketConn.SetReadDeadline(aLongTimeAgo) // Unblock reads | ||||
| 	} | ||||
| 
 | ||||
| 	if srv.Listener != nil { | ||||
| 		srv.Listener.Close() | ||||
| 	} | ||||
| 
 | ||||
| 	for rw := range srv.conns { | ||||
| 		rw.SetReadDeadline(aLongTimeAgo) // Unblock reads | ||||
| 	} | ||||
| 
 | ||||
| 	srv.lock.Unlock() | ||||
| 
 | ||||
| 	if testShutdownNotify != nil { | ||||
| 		testShutdownNotify.Broadcast() | ||||
| 	} | ||||
| 
 | ||||
| 	var ctxErr error | ||||
| 	select { | ||||
| 	case <-srv.shutdown: | ||||
| 	case <-ctx.Done(): | ||||
| 		ctxErr = ctx.Err() | ||||
| 	} | ||||
| 
 | ||||
| 	if srv.PacketConn != nil { | ||||
| 		srv.PacketConn.Close() | ||||
| 	} | ||||
| 
 | ||||
| 	return ctxErr | ||||
| } | ||||
| 
 | ||||
| var testShutdownNotify *sync.Cond | ||||
| 
 | ||||
| // getReadTimeout is a helper func to use system timeout if server did not intend to change it. | ||||
| func (srv *Server) getReadTimeout() time.Duration { | ||||
| 	if srv.ReadTimeout != 0 { | ||||
| 		return srv.ReadTimeout | ||||
| 	} | ||||
| 	return dnsTimeout | ||||
| } | ||||
| 
 | ||||
| // serveTCP starts a TCP listener for the server. | ||||
| func (srv *Server) serveTCP(l net.Listener) error { | ||||
| 	defer l.Close() | ||||
| 
 | ||||
| 	if srv.NotifyStartedFunc != nil { | ||||
| 		srv.NotifyStartedFunc() | ||||
| 	} | ||||
| 
 | ||||
| 	var wg sync.WaitGroup | ||||
| 	defer func() { | ||||
| 		wg.Wait() | ||||
| 		close(srv.shutdown) | ||||
| 	}() | ||||
| 
 | ||||
| 	for srv.isStarted() { | ||||
| 		rw, err := l.Accept() | ||||
| 		if err != nil { | ||||
| 			if !srv.isStarted() { | ||||
| 				return nil | ||||
| 			} | ||||
| 			if neterr, ok := err.(net.Error); ok && neterr.Temporary() { | ||||
| 				continue | ||||
| 			} | ||||
| 			return err | ||||
| 		} | ||||
| 		srv.lock.Lock() | ||||
| 		// Track the connection to allow unblocking reads on shutdown. | ||||
| 		srv.conns[rw] = struct{}{} | ||||
| 		srv.lock.Unlock() | ||||
| 		wg.Add(1) | ||||
| 		go srv.serveTCPConn(&wg, rw) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // serveUDP starts a UDP listener for the server. | ||||
| func (srv *Server) serveUDP(l net.PacketConn) error { | ||||
| 	defer l.Close() | ||||
| 
 | ||||
| 	reader := Reader(defaultReader{srv}) | ||||
| 	if srv.DecorateReader != nil { | ||||
| 		reader = srv.DecorateReader(reader) | ||||
| 	} | ||||
| 
 | ||||
| 	lUDP, isUDP := l.(*net.UDPConn) | ||||
| 	readerPC, canPacketConn := reader.(PacketConnReader) | ||||
| 	if !isUDP && !canPacketConn { | ||||
| 		return &Error{err: "PacketConnReader was not implemented on Reader returned from DecorateReader but is required for net.PacketConn"} | ||||
| 	} | ||||
| 
 | ||||
| 	if srv.NotifyStartedFunc != nil { | ||||
| 		srv.NotifyStartedFunc() | ||||
| 	} | ||||
| 
 | ||||
| 	var wg sync.WaitGroup | ||||
| 	defer func() { | ||||
| 		wg.Wait() | ||||
| 		close(srv.shutdown) | ||||
| 	}() | ||||
| 
 | ||||
| 	rtimeout := srv.getReadTimeout() | ||||
| 	// deadline is not used here | ||||
| 	for srv.isStarted() { | ||||
| 		var ( | ||||
| 			m    []byte | ||||
| 			sPC  net.Addr | ||||
| 			sUDP *SessionUDP | ||||
| 			err  error | ||||
| 		) | ||||
| 		if isUDP { | ||||
| 			m, sUDP, err = reader.ReadUDP(lUDP, rtimeout) | ||||
| 		} else { | ||||
| 			m, sPC, err = readerPC.ReadPacketConn(l, rtimeout) | ||||
| 		} | ||||
| 		if err != nil { | ||||
| 			if !srv.isStarted() { | ||||
| 				return nil | ||||
| 			} | ||||
| 			if netErr, ok := err.(net.Error); ok && netErr.Temporary() { | ||||
| 				continue | ||||
| 			} | ||||
| 			return err | ||||
| 		} | ||||
| 		if len(m) < headerSize { | ||||
| 			if cap(m) == srv.UDPSize { | ||||
| 				srv.udpPool.Put(m[:srv.UDPSize]) | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 		wg.Add(1) | ||||
| 		go srv.serveUDPPacket(&wg, m, l, sUDP, sPC) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Serve a new TCP connection. | ||||
| func (srv *Server) serveTCPConn(wg *sync.WaitGroup, rw net.Conn) { | ||||
| 	w := &response{tsigProvider: srv.tsigProvider(), tcp: rw} | ||||
| 	if srv.DecorateWriter != nil { | ||||
| 		w.writer = srv.DecorateWriter(w) | ||||
| 	} else { | ||||
| 		w.writer = w | ||||
| 	} | ||||
| 
 | ||||
| 	reader := Reader(defaultReader{srv}) | ||||
| 	if srv.DecorateReader != nil { | ||||
| 		reader = srv.DecorateReader(reader) | ||||
| 	} | ||||
| 
 | ||||
| 	idleTimeout := tcpIdleTimeout | ||||
| 	if srv.IdleTimeout != nil { | ||||
| 		idleTimeout = srv.IdleTimeout() | ||||
| 	} | ||||
| 
 | ||||
| 	timeout := srv.getReadTimeout() | ||||
| 
 | ||||
| 	limit := srv.MaxTCPQueries | ||||
| 	if limit == 0 { | ||||
| 		limit = maxTCPQueries | ||||
| 	} | ||||
| 
 | ||||
| 	for q := 0; (q < limit || limit == -1) && srv.isStarted(); q++ { | ||||
| 		m, err := reader.ReadTCP(w.tcp, timeout) | ||||
| 		if err != nil { | ||||
| 			// TODO(tmthrgd): handle error | ||||
| 			break | ||||
| 		} | ||||
| 		srv.serveDNS(m, w) | ||||
| 		if w.closed { | ||||
| 			break // Close() was called | ||||
| 		} | ||||
| 		if w.hijacked { | ||||
| 			break // client will call Close() themselves | ||||
| 		} | ||||
| 		// The first read uses the read timeout, the rest use the | ||||
| 		// idle timeout. | ||||
| 		timeout = idleTimeout | ||||
| 	} | ||||
| 
 | ||||
| 	if !w.hijacked { | ||||
| 		w.Close() | ||||
| 	} | ||||
| 
 | ||||
| 	srv.lock.Lock() | ||||
| 	delete(srv.conns, w.tcp) | ||||
| 	srv.lock.Unlock() | ||||
| 
 | ||||
| 	wg.Done() | ||||
| } | ||||
| 
 | ||||
| // Serve a new UDP request. | ||||
| func (srv *Server) serveUDPPacket(wg *sync.WaitGroup, m []byte, u net.PacketConn, udpSession *SessionUDP, pcSession net.Addr) { | ||||
| 	w := &response{tsigProvider: srv.tsigProvider(), udp: u, udpSession: udpSession, pcSession: pcSession} | ||||
| 	if srv.DecorateWriter != nil { | ||||
| 		w.writer = srv.DecorateWriter(w) | ||||
| 	} else { | ||||
| 		w.writer = w | ||||
| 	} | ||||
| 
 | ||||
| 	srv.serveDNS(m, w) | ||||
| 	wg.Done() | ||||
| } | ||||
| 
 | ||||
| func (srv *Server) serveDNS(m []byte, w *response) { | ||||
| 	dh, off, err := unpackMsgHdr(m, 0) | ||||
| 	if err != nil { | ||||
| 		// Let client hang, they are sending crap; any reply can be used to amplify. | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	req := new(Msg) | ||||
| 	req.setHdr(dh) | ||||
| 
 | ||||
| 	switch action := srv.MsgAcceptFunc(dh); action { | ||||
| 	case MsgAccept: | ||||
| 		if req.unpack(dh, m, off) == nil { | ||||
| 			break | ||||
| 		} | ||||
| 
 | ||||
| 		fallthrough | ||||
| 	case MsgReject, MsgRejectNotImplemented: | ||||
| 		opcode := req.Opcode | ||||
| 		req.SetRcodeFormatError(req) | ||||
| 		req.Zero = false | ||||
| 		if action == MsgRejectNotImplemented { | ||||
| 			req.Opcode = opcode | ||||
| 			req.Rcode = RcodeNotImplemented | ||||
| 		} | ||||
| 
 | ||||
| 		// Are we allowed to delete any OPT records here? | ||||
| 		req.Ns, req.Answer, req.Extra = nil, nil, nil | ||||
| 
 | ||||
| 		w.WriteMsg(req) | ||||
| 		fallthrough | ||||
| 	case MsgIgnore: | ||||
| 		if w.udp != nil && cap(m) == srv.UDPSize { | ||||
| 			srv.udpPool.Put(m[:srv.UDPSize]) | ||||
| 		} | ||||
| 
 | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	w.tsigStatus = nil | ||||
| 	if w.tsigProvider != nil { | ||||
| 		if t := req.IsTsig(); t != nil { | ||||
| 			w.tsigStatus = tsigVerifyProvider(m, w.tsigProvider, "", false) | ||||
| 			w.tsigTimersOnly = false | ||||
| 			w.tsigRequestMAC = t.MAC | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if w.udp != nil && cap(m) == srv.UDPSize { | ||||
| 		srv.udpPool.Put(m[:srv.UDPSize]) | ||||
| 	} | ||||
| 
 | ||||
| 	srv.Handler.ServeDNS(w, req) // Writes back to the client | ||||
| } | ||||
| 
 | ||||
| func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) { | ||||
| 	// If we race with ShutdownContext, the read deadline may | ||||
| 	// have been set in the distant past to unblock the read | ||||
| 	// below. We must not override it, otherwise we may block | ||||
| 	// ShutdownContext. | ||||
| 	srv.lock.RLock() | ||||
| 	if srv.started { | ||||
| 		conn.SetReadDeadline(time.Now().Add(timeout)) | ||||
| 	} | ||||
| 	srv.lock.RUnlock() | ||||
| 
 | ||||
| 	var length uint16 | ||||
| 	if err := binary.Read(conn, binary.BigEndian, &length); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	m := make([]byte, length) | ||||
| 	if _, err := io.ReadFull(conn, m); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return m, nil | ||||
| } | ||||
| 
 | ||||
| func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) { | ||||
| 	srv.lock.RLock() | ||||
| 	if srv.started { | ||||
| 		// See the comment in readTCP above. | ||||
| 		conn.SetReadDeadline(time.Now().Add(timeout)) | ||||
| 	} | ||||
| 	srv.lock.RUnlock() | ||||
| 
 | ||||
| 	m := srv.udpPool.Get().([]byte) | ||||
| 	n, s, err := ReadFromSessionUDP(conn, m) | ||||
| 	if err != nil { | ||||
| 		srv.udpPool.Put(m) | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	m = m[:n] | ||||
| 	return m, s, nil | ||||
| } | ||||
| 
 | ||||
| func (srv *Server) readPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error) { | ||||
| 	srv.lock.RLock() | ||||
| 	if srv.started { | ||||
| 		// See the comment in readTCP above. | ||||
| 		conn.SetReadDeadline(time.Now().Add(timeout)) | ||||
| 	} | ||||
| 	srv.lock.RUnlock() | ||||
| 
 | ||||
| 	m := srv.udpPool.Get().([]byte) | ||||
| 	n, addr, err := conn.ReadFrom(m) | ||||
| 	if err != nil { | ||||
| 		srv.udpPool.Put(m) | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	m = m[:n] | ||||
| 	return m, addr, nil | ||||
| } | ||||
| 
 | ||||
| // WriteMsg implements the ResponseWriter.WriteMsg method. | ||||
| func (w *response) WriteMsg(m *Msg) (err error) { | ||||
| 	if w.closed { | ||||
| 		return &Error{err: "WriteMsg called after Close"} | ||||
| 	} | ||||
| 
 | ||||
| 	var data []byte | ||||
| 	if w.tsigProvider != nil { // if no provider, dont check for the tsig (which is a longer check) | ||||
| 		if t := m.IsTsig(); t != nil { | ||||
| 			data, w.tsigRequestMAC, err = tsigGenerateProvider(m, w.tsigProvider, w.tsigRequestMAC, w.tsigTimersOnly) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			_, err = w.writer.Write(data) | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	data, err = m.Pack() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = w.writer.Write(data) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // Write implements the ResponseWriter.Write method. | ||||
| func (w *response) Write(m []byte) (int, error) { | ||||
| 	if w.closed { | ||||
| 		return 0, &Error{err: "Write called after Close"} | ||||
| 	} | ||||
| 
 | ||||
| 	switch { | ||||
| 	case w.udp != nil: | ||||
| 		if u, ok := w.udp.(*net.UDPConn); ok { | ||||
| 			return WriteToSessionUDP(u, m, w.udpSession) | ||||
| 		} | ||||
| 		return w.udp.WriteTo(m, w.pcSession) | ||||
| 	case w.tcp != nil: | ||||
| 		if len(m) > MaxMsgSize { | ||||
| 			return 0, &Error{err: "message too large"} | ||||
| 		} | ||||
| 
 | ||||
| 		msg := make([]byte, 2+len(m)) | ||||
| 		binary.BigEndian.PutUint16(msg, uint16(len(m))) | ||||
| 		copy(msg[2:], m) | ||||
| 		return w.tcp.Write(msg) | ||||
| 	default: | ||||
| 		panic("dns: internal error: udp and tcp both nil") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // LocalAddr implements the ResponseWriter.LocalAddr method. | ||||
| func (w *response) LocalAddr() net.Addr { | ||||
| 	switch { | ||||
| 	case w.udp != nil: | ||||
| 		return w.udp.LocalAddr() | ||||
| 	case w.tcp != nil: | ||||
| 		return w.tcp.LocalAddr() | ||||
| 	default: | ||||
| 		panic("dns: internal error: udp and tcp both nil") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // RemoteAddr implements the ResponseWriter.RemoteAddr method. | ||||
| func (w *response) RemoteAddr() net.Addr { | ||||
| 	switch { | ||||
| 	case w.udpSession != nil: | ||||
| 		return w.udpSession.RemoteAddr() | ||||
| 	case w.pcSession != nil: | ||||
| 		return w.pcSession | ||||
| 	case w.tcp != nil: | ||||
| 		return w.tcp.RemoteAddr() | ||||
| 	default: | ||||
| 		panic("dns: internal error: udpSession, pcSession and tcp are all nil") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // TsigStatus implements the ResponseWriter.TsigStatus method. | ||||
| func (w *response) TsigStatus() error { return w.tsigStatus } | ||||
| 
 | ||||
| // TsigTimersOnly implements the ResponseWriter.TsigTimersOnly method. | ||||
| func (w *response) TsigTimersOnly(b bool) { w.tsigTimersOnly = b } | ||||
| 
 | ||||
| // Hijack implements the ResponseWriter.Hijack method. | ||||
| func (w *response) Hijack() { w.hijacked = true } | ||||
| 
 | ||||
| // Close implements the ResponseWriter.Close method | ||||
| func (w *response) Close() error { | ||||
| 	if w.closed { | ||||
| 		return &Error{err: "connection already closed"} | ||||
| 	} | ||||
| 	w.closed = true | ||||
| 
 | ||||
| 	switch { | ||||
| 	case w.udp != nil: | ||||
| 		// Can't close the udp conn, as that is actually the listener. | ||||
| 		return nil | ||||
| 	case w.tcp != nil: | ||||
| 		return w.tcp.Close() | ||||
| 	default: | ||||
| 		panic("dns: internal error: udp and tcp both nil") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // ConnectionState() implements the ConnectionStater.ConnectionState() interface. | ||||
| func (w *response) ConnectionState() *tls.ConnectionState { | ||||
| 	type tlsConnectionStater interface { | ||||
| 		ConnectionState() tls.ConnectionState | ||||
| 	} | ||||
| 	if v, ok := w.tcp.(tlsConnectionStater); ok { | ||||
| 		t := v.ConnectionState() | ||||
| 		return &t | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										194
									
								
								vendor/github.com/miekg/dns/sig0.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								vendor/github.com/miekg/dns/sig0.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,194 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/ecdsa" | ||||
| 	"crypto/ed25519" | ||||
| 	"crypto/rsa" | ||||
| 	"encoding/binary" | ||||
| 	"math/big" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // Sign signs a dns.Msg. It fills the signature with the appropriate data. | ||||
| // The SIG record should have the SignerName, KeyTag, Algorithm, Inception | ||||
| // and Expiration set. | ||||
| func (rr *SIG) Sign(k crypto.Signer, m *Msg) ([]byte, error) { | ||||
| 	if k == nil { | ||||
| 		return nil, ErrPrivKey | ||||
| 	} | ||||
| 	if rr.KeyTag == 0 || rr.SignerName == "" || rr.Algorithm == 0 { | ||||
| 		return nil, ErrKey | ||||
| 	} | ||||
| 
 | ||||
| 	rr.Hdr = RR_Header{Name: ".", Rrtype: TypeSIG, Class: ClassANY, Ttl: 0} | ||||
| 	rr.OrigTtl, rr.TypeCovered, rr.Labels = 0, 0, 0 | ||||
| 
 | ||||
| 	buf := make([]byte, m.Len()+Len(rr)) | ||||
| 	mbuf, err := m.PackBuffer(buf) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if &buf[0] != &mbuf[0] { | ||||
| 		return nil, ErrBuf | ||||
| 	} | ||||
| 	off, err := PackRR(rr, buf, len(mbuf), nil, false) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	buf = buf[:off:cap(buf)] | ||||
| 
 | ||||
| 	h, cryptohash, err := hashFromAlgorithm(rr.Algorithm) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	// Write SIG rdata | ||||
| 	h.Write(buf[len(mbuf)+1+2+2+4+2:]) | ||||
| 	// Write message | ||||
| 	h.Write(buf[:len(mbuf)]) | ||||
| 
 | ||||
| 	signature, err := sign(k, h.Sum(nil), cryptohash, rr.Algorithm) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	rr.Signature = toBase64(signature) | ||||
| 
 | ||||
| 	buf = append(buf, signature...) | ||||
| 	if len(buf) > int(^uint16(0)) { | ||||
| 		return nil, ErrBuf | ||||
| 	} | ||||
| 	// Adjust sig data length | ||||
| 	rdoff := len(mbuf) + 1 + 2 + 2 + 4 | ||||
| 	rdlen := binary.BigEndian.Uint16(buf[rdoff:]) | ||||
| 	rdlen += uint16(len(signature)) | ||||
| 	binary.BigEndian.PutUint16(buf[rdoff:], rdlen) | ||||
| 	// Adjust additional count | ||||
| 	adc := binary.BigEndian.Uint16(buf[10:]) | ||||
| 	adc++ | ||||
| 	binary.BigEndian.PutUint16(buf[10:], adc) | ||||
| 	return buf, nil | ||||
| } | ||||
| 
 | ||||
| // Verify validates the message buf using the key k. | ||||
| // It's assumed that buf is a valid message from which rr was unpacked. | ||||
| func (rr *SIG) Verify(k *KEY, buf []byte) error { | ||||
| 	if k == nil { | ||||
| 		return ErrKey | ||||
| 	} | ||||
| 	if rr.KeyTag == 0 || rr.SignerName == "" || rr.Algorithm == 0 { | ||||
| 		return ErrKey | ||||
| 	} | ||||
| 
 | ||||
| 	h, cryptohash, err := hashFromAlgorithm(rr.Algorithm) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	buflen := len(buf) | ||||
| 	qdc := binary.BigEndian.Uint16(buf[4:]) | ||||
| 	anc := binary.BigEndian.Uint16(buf[6:]) | ||||
| 	auc := binary.BigEndian.Uint16(buf[8:]) | ||||
| 	adc := binary.BigEndian.Uint16(buf[10:]) | ||||
| 	offset := headerSize | ||||
| 	for i := uint16(0); i < qdc && offset < buflen; i++ { | ||||
| 		_, offset, err = UnpackDomainName(buf, offset) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		// Skip past Type and Class | ||||
| 		offset += 2 + 2 | ||||
| 	} | ||||
| 	for i := uint16(1); i < anc+auc+adc && offset < buflen; i++ { | ||||
| 		_, offset, err = UnpackDomainName(buf, offset) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		// Skip past Type, Class and TTL | ||||
| 		offset += 2 + 2 + 4 | ||||
| 		if offset+1 >= buflen { | ||||
| 			continue | ||||
| 		} | ||||
| 		rdlen := binary.BigEndian.Uint16(buf[offset:]) | ||||
| 		offset += 2 | ||||
| 		offset += int(rdlen) | ||||
| 	} | ||||
| 	if offset >= buflen { | ||||
| 		return &Error{err: "overflowing unpacking signed message"} | ||||
| 	} | ||||
| 
 | ||||
| 	// offset should be just prior to SIG | ||||
| 	bodyend := offset | ||||
| 	// owner name SHOULD be root | ||||
| 	_, offset, err = UnpackDomainName(buf, offset) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// Skip Type, Class, TTL, RDLen | ||||
| 	offset += 2 + 2 + 4 + 2 | ||||
| 	sigstart := offset | ||||
| 	// Skip Type Covered, Algorithm, Labels, Original TTL | ||||
| 	offset += 2 + 1 + 1 + 4 | ||||
| 	if offset+4+4 >= buflen { | ||||
| 		return &Error{err: "overflow unpacking signed message"} | ||||
| 	} | ||||
| 	expire := binary.BigEndian.Uint32(buf[offset:]) | ||||
| 	offset += 4 | ||||
| 	incept := binary.BigEndian.Uint32(buf[offset:]) | ||||
| 	offset += 4 | ||||
| 	now := uint32(time.Now().Unix()) | ||||
| 	if now < incept || now > expire { | ||||
| 		return ErrTime | ||||
| 	} | ||||
| 	// Skip key tag | ||||
| 	offset += 2 | ||||
| 	var signername string | ||||
| 	signername, offset, err = UnpackDomainName(buf, offset) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// If key has come from the DNS name compression might | ||||
| 	// have mangled the case of the name | ||||
| 	if !strings.EqualFold(signername, k.Header().Name) { | ||||
| 		return &Error{err: "signer name doesn't match key name"} | ||||
| 	} | ||||
| 	sigend := offset | ||||
| 	h.Write(buf[sigstart:sigend]) | ||||
| 	h.Write(buf[:10]) | ||||
| 	h.Write([]byte{ | ||||
| 		byte((adc - 1) << 8), | ||||
| 		byte(adc - 1), | ||||
| 	}) | ||||
| 	h.Write(buf[12:bodyend]) | ||||
| 
 | ||||
| 	hashed := h.Sum(nil) | ||||
| 	sig := buf[sigend:] | ||||
| 	switch k.Algorithm { | ||||
| 	case RSASHA1, RSASHA256, RSASHA512: | ||||
| 		pk := k.publicKeyRSA() | ||||
| 		if pk != nil { | ||||
| 			return rsa.VerifyPKCS1v15(pk, cryptohash, hashed, sig) | ||||
| 		} | ||||
| 	case ECDSAP256SHA256, ECDSAP384SHA384: | ||||
| 		pk := k.publicKeyECDSA() | ||||
| 		r := new(big.Int).SetBytes(sig[:len(sig)/2]) | ||||
| 		s := new(big.Int).SetBytes(sig[len(sig)/2:]) | ||||
| 		if pk != nil { | ||||
| 			if ecdsa.Verify(pk, hashed, r, s) { | ||||
| 				return nil | ||||
| 			} | ||||
| 			return ErrSig | ||||
| 		} | ||||
| 	case ED25519: | ||||
| 		pk := k.publicKeyED25519() | ||||
| 		if pk != nil { | ||||
| 			if ed25519.Verify(pk, hashed, sig) { | ||||
| 				return nil | ||||
| 			} | ||||
| 			return ErrSig | ||||
| 		} | ||||
| 	} | ||||
| 	return ErrKeyAlg | ||||
| } | ||||
							
								
								
									
										61
									
								
								vendor/github.com/miekg/dns/singleinflight.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								vendor/github.com/miekg/dns/singleinflight.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | |||
| // 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. | ||||
| 
 | ||||
| // Adapted for dns package usage by Miek Gieben. | ||||
| 
 | ||||
| package dns | ||||
| 
 | ||||
| import "sync" | ||||
| import "time" | ||||
| 
 | ||||
| // call is an in-flight or completed singleflight.Do call | ||||
| type call struct { | ||||
| 	wg   sync.WaitGroup | ||||
| 	val  *Msg | ||||
| 	rtt  time.Duration | ||||
| 	err  error | ||||
| 	dups int | ||||
| } | ||||
| 
 | ||||
| // singleflight represents a class of work and forms a namespace in | ||||
| // which units of work can be executed with duplicate suppression. | ||||
| type singleflight struct { | ||||
| 	sync.Mutex                  // protects m | ||||
| 	m          map[string]*call // lazily initialized | ||||
| 
 | ||||
| 	dontDeleteForTesting bool // this is only to be used by TestConcurrentExchanges | ||||
| } | ||||
| 
 | ||||
| // Do executes and returns the results of the given function, making | ||||
| // sure that only one execution is in-flight for a given key at a | ||||
| // time. If a duplicate comes in, the duplicate caller waits for the | ||||
| // original to complete and receives the same results. | ||||
| // The return value shared indicates whether v was given to multiple callers. | ||||
| func (g *singleflight) Do(key string, fn func() (*Msg, time.Duration, error)) (v *Msg, rtt time.Duration, err error, shared bool) { | ||||
| 	g.Lock() | ||||
| 	if g.m == nil { | ||||
| 		g.m = make(map[string]*call) | ||||
| 	} | ||||
| 	if c, ok := g.m[key]; ok { | ||||
| 		c.dups++ | ||||
| 		g.Unlock() | ||||
| 		c.wg.Wait() | ||||
| 		return c.val, c.rtt, c.err, true | ||||
| 	} | ||||
| 	c := new(call) | ||||
| 	c.wg.Add(1) | ||||
| 	g.m[key] = c | ||||
| 	g.Unlock() | ||||
| 
 | ||||
| 	c.val, c.rtt, c.err = fn() | ||||
| 	c.wg.Done() | ||||
| 
 | ||||
| 	if !g.dontDeleteForTesting { | ||||
| 		g.Lock() | ||||
| 		delete(g.m, key) | ||||
| 		g.Unlock() | ||||
| 	} | ||||
| 
 | ||||
| 	return c.val, c.rtt, c.err, c.dups > 0 | ||||
| } | ||||
							
								
								
									
										44
									
								
								vendor/github.com/miekg/dns/smimea.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/miekg/dns/smimea.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/sha256" | ||||
| 	"crypto/x509" | ||||
| 	"encoding/hex" | ||||
| ) | ||||
| 
 | ||||
| // Sign creates a SMIMEA record from an SSL certificate. | ||||
| func (r *SMIMEA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) { | ||||
| 	r.Hdr.Rrtype = TypeSMIMEA | ||||
| 	r.Usage = uint8(usage) | ||||
| 	r.Selector = uint8(selector) | ||||
| 	r.MatchingType = uint8(matchingType) | ||||
| 
 | ||||
| 	r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // Verify verifies a SMIMEA record against an SSL certificate. If it is OK | ||||
| // a nil error is returned. | ||||
| func (r *SMIMEA) Verify(cert *x509.Certificate) error { | ||||
| 	c, err := CertificateToDANE(r.Selector, r.MatchingType, cert) | ||||
| 	if err != nil { | ||||
| 		return err // Not also ErrSig? | ||||
| 	} | ||||
| 	if r.Certificate == c { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return ErrSig // ErrSig, really? | ||||
| } | ||||
| 
 | ||||
| // SMIMEAName returns the ownername of a SMIMEA resource record as per the | ||||
| // format specified in RFC 'draft-ietf-dane-smime-12' Section 2 and 3 | ||||
| func SMIMEAName(email, domain string) (string, error) { | ||||
| 	hasher := sha256.New() | ||||
| 	hasher.Write([]byte(email)) | ||||
| 
 | ||||
| 	// RFC Section 3: "The local-part is hashed using the SHA2-256 | ||||
| 	// algorithm with the hash truncated to 28 octets and | ||||
| 	// represented in its hexadecimal representation to become the | ||||
| 	// left-most label in the prepared domain name" | ||||
| 	return hex.EncodeToString(hasher.Sum(nil)[:28]) + "." + "_smimecert." + domain, nil | ||||
| } | ||||
							
								
								
									
										935
									
								
								vendor/github.com/miekg/dns/svcb.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										935
									
								
								vendor/github.com/miekg/dns/svcb.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,935 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/binary" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // SVCBKey is the type of the keys used in the SVCB RR. | ||||
| type SVCBKey uint16 | ||||
| 
 | ||||
| // Keys defined in draft-ietf-dnsop-svcb-https-08 Section 14.3.2. | ||||
| const ( | ||||
| 	SVCB_MANDATORY SVCBKey = iota | ||||
| 	SVCB_ALPN | ||||
| 	SVCB_NO_DEFAULT_ALPN | ||||
| 	SVCB_PORT | ||||
| 	SVCB_IPV4HINT | ||||
| 	SVCB_ECHCONFIG | ||||
| 	SVCB_IPV6HINT | ||||
| 	SVCB_DOHPATH // draft-ietf-add-svcb-dns-02 Section 9 | ||||
| 
 | ||||
| 	svcb_RESERVED SVCBKey = 65535 | ||||
| ) | ||||
| 
 | ||||
| var svcbKeyToStringMap = map[SVCBKey]string{ | ||||
| 	SVCB_MANDATORY:       "mandatory", | ||||
| 	SVCB_ALPN:            "alpn", | ||||
| 	SVCB_NO_DEFAULT_ALPN: "no-default-alpn", | ||||
| 	SVCB_PORT:            "port", | ||||
| 	SVCB_IPV4HINT:        "ipv4hint", | ||||
| 	SVCB_ECHCONFIG:       "ech", | ||||
| 	SVCB_IPV6HINT:        "ipv6hint", | ||||
| 	SVCB_DOHPATH:         "dohpath", | ||||
| } | ||||
| 
 | ||||
| var svcbStringToKeyMap = reverseSVCBKeyMap(svcbKeyToStringMap) | ||||
| 
 | ||||
| func reverseSVCBKeyMap(m map[SVCBKey]string) map[string]SVCBKey { | ||||
| 	n := make(map[string]SVCBKey, len(m)) | ||||
| 	for u, s := range m { | ||||
| 		n[s] = u | ||||
| 	} | ||||
| 	return n | ||||
| } | ||||
| 
 | ||||
| // String takes the numerical code of an SVCB key and returns its name. | ||||
| // Returns an empty string for reserved keys. | ||||
| // Accepts unassigned keys as well as experimental/private keys. | ||||
| func (key SVCBKey) String() string { | ||||
| 	if x := svcbKeyToStringMap[key]; x != "" { | ||||
| 		return x | ||||
| 	} | ||||
| 	if key == svcb_RESERVED { | ||||
| 		return "" | ||||
| 	} | ||||
| 	return "key" + strconv.FormatUint(uint64(key), 10) | ||||
| } | ||||
| 
 | ||||
| // svcbStringToKey returns the numerical code of an SVCB key. | ||||
| // Returns svcb_RESERVED for reserved/invalid keys. | ||||
| // Accepts unassigned keys as well as experimental/private keys. | ||||
| func svcbStringToKey(s string) SVCBKey { | ||||
| 	if strings.HasPrefix(s, "key") { | ||||
| 		a, err := strconv.ParseUint(s[3:], 10, 16) | ||||
| 		// no leading zeros | ||||
| 		// key shouldn't be registered | ||||
| 		if err != nil || a == 65535 || s[3] == '0' || svcbKeyToStringMap[SVCBKey(a)] != "" { | ||||
| 			return svcb_RESERVED | ||||
| 		} | ||||
| 		return SVCBKey(a) | ||||
| 	} | ||||
| 	if key, ok := svcbStringToKeyMap[s]; ok { | ||||
| 		return key | ||||
| 	} | ||||
| 	return svcb_RESERVED | ||||
| } | ||||
| 
 | ||||
| func (rr *SVCB) parse(c *zlexer, o string) *ParseError { | ||||
| 	l, _ := c.Next() | ||||
| 	i, e := strconv.ParseUint(l.token, 10, 16) | ||||
| 	if e != nil || l.err { | ||||
| 		return &ParseError{l.token, "bad SVCB priority", l} | ||||
| 	} | ||||
| 	rr.Priority = uint16(i) | ||||
| 
 | ||||
| 	c.Next()        // zBlank | ||||
| 	l, _ = c.Next() // zString | ||||
| 	rr.Target = l.token | ||||
| 
 | ||||
| 	name, nameOk := toAbsoluteName(l.token, o) | ||||
| 	if l.err || !nameOk { | ||||
| 		return &ParseError{l.token, "bad SVCB Target", l} | ||||
| 	} | ||||
| 	rr.Target = name | ||||
| 
 | ||||
| 	// Values (if any) | ||||
| 	l, _ = c.Next() | ||||
| 	var xs []SVCBKeyValue | ||||
| 	// Helps require whitespace between pairs. | ||||
| 	// Prevents key1000="a"key1001=... | ||||
| 	canHaveNextKey := true | ||||
| 	for l.value != zNewline && l.value != zEOF { | ||||
| 		switch l.value { | ||||
| 		case zString: | ||||
| 			if !canHaveNextKey { | ||||
| 				// The key we can now read was probably meant to be | ||||
| 				// a part of the last value. | ||||
| 				return &ParseError{l.token, "bad SVCB value quotation", l} | ||||
| 			} | ||||
| 
 | ||||
| 			// In key=value pairs, value does not have to be quoted unless value | ||||
| 			// contains whitespace. And keys don't need to have values. | ||||
| 			// Similarly, keys with an equality signs after them don't need values. | ||||
| 			// l.token includes at least up to the first equality sign. | ||||
| 			idx := strings.IndexByte(l.token, '=') | ||||
| 			var key, value string | ||||
| 			if idx < 0 { | ||||
| 				// Key with no value and no equality sign | ||||
| 				key = l.token | ||||
| 			} else if idx == 0 { | ||||
| 				return &ParseError{l.token, "bad SVCB key", l} | ||||
| 			} else { | ||||
| 				key, value = l.token[:idx], l.token[idx+1:] | ||||
| 
 | ||||
| 				if value == "" { | ||||
| 					// We have a key and an equality sign. Maybe we have nothing | ||||
| 					// after "=" or we have a double quote. | ||||
| 					l, _ = c.Next() | ||||
| 					if l.value == zQuote { | ||||
| 						// Only needed when value ends with double quotes. | ||||
| 						// Any value starting with zQuote ends with it. | ||||
| 						canHaveNextKey = false | ||||
| 
 | ||||
| 						l, _ = c.Next() | ||||
| 						switch l.value { | ||||
| 						case zString: | ||||
| 							// We have a value in double quotes. | ||||
| 							value = l.token | ||||
| 							l, _ = c.Next() | ||||
| 							if l.value != zQuote { | ||||
| 								return &ParseError{l.token, "SVCB unterminated value", l} | ||||
| 							} | ||||
| 						case zQuote: | ||||
| 							// There's nothing in double quotes. | ||||
| 						default: | ||||
| 							return &ParseError{l.token, "bad SVCB value", l} | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			kv := makeSVCBKeyValue(svcbStringToKey(key)) | ||||
| 			if kv == nil { | ||||
| 				return &ParseError{l.token, "bad SVCB key", l} | ||||
| 			} | ||||
| 			if err := kv.parse(value); err != nil { | ||||
| 				return &ParseError{l.token, err.Error(), l} | ||||
| 			} | ||||
| 			xs = append(xs, kv) | ||||
| 		case zQuote: | ||||
| 			return &ParseError{l.token, "SVCB key can't contain double quotes", l} | ||||
| 		case zBlank: | ||||
| 			canHaveNextKey = true | ||||
| 		default: | ||||
| 			return &ParseError{l.token, "bad SVCB values", l} | ||||
| 		} | ||||
| 		l, _ = c.Next() | ||||
| 	} | ||||
| 
 | ||||
| 	// "In AliasMode, records SHOULD NOT include any SvcParams, and recipients MUST | ||||
| 	// ignore any SvcParams that are present." | ||||
| 	// However, we don't check rr.Priority == 0 && len(xs) > 0 here | ||||
| 	// It is the responsibility of the user of the library to check this. | ||||
| 	// This is to encourage the fixing of the source of this error. | ||||
| 
 | ||||
| 	rr.Value = xs | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // makeSVCBKeyValue returns an SVCBKeyValue struct with the key or nil for reserved keys. | ||||
| func makeSVCBKeyValue(key SVCBKey) SVCBKeyValue { | ||||
| 	switch key { | ||||
| 	case SVCB_MANDATORY: | ||||
| 		return new(SVCBMandatory) | ||||
| 	case SVCB_ALPN: | ||||
| 		return new(SVCBAlpn) | ||||
| 	case SVCB_NO_DEFAULT_ALPN: | ||||
| 		return new(SVCBNoDefaultAlpn) | ||||
| 	case SVCB_PORT: | ||||
| 		return new(SVCBPort) | ||||
| 	case SVCB_IPV4HINT: | ||||
| 		return new(SVCBIPv4Hint) | ||||
| 	case SVCB_ECHCONFIG: | ||||
| 		return new(SVCBECHConfig) | ||||
| 	case SVCB_IPV6HINT: | ||||
| 		return new(SVCBIPv6Hint) | ||||
| 	case SVCB_DOHPATH: | ||||
| 		return new(SVCBDoHPath) | ||||
| 	case svcb_RESERVED: | ||||
| 		return nil | ||||
| 	default: | ||||
| 		e := new(SVCBLocal) | ||||
| 		e.KeyCode = key | ||||
| 		return e | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SVCB RR. See RFC xxxx (https://tools.ietf.org/html/draft-ietf-dnsop-svcb-https-08). | ||||
| // | ||||
| // NOTE: The HTTPS/SVCB RFCs are in the draft stage. | ||||
| // The API, including constants and types related to SVCBKeyValues, may | ||||
| // change in future versions in accordance with the latest drafts. | ||||
| type SVCB struct { | ||||
| 	Hdr      RR_Header | ||||
| 	Priority uint16         // If zero, Value must be empty or discarded by the user of this library | ||||
| 	Target   string         `dns:"domain-name"` | ||||
| 	Value    []SVCBKeyValue `dns:"pairs"` | ||||
| } | ||||
| 
 | ||||
| // HTTPS RR. Everything valid for SVCB applies to HTTPS as well. | ||||
| // Except that the HTTPS record is intended for use with the HTTP and HTTPS protocols. | ||||
| // | ||||
| // NOTE: The HTTPS/SVCB RFCs are in the draft stage. | ||||
| // The API, including constants and types related to SVCBKeyValues, may | ||||
| // change in future versions in accordance with the latest drafts. | ||||
| type HTTPS struct { | ||||
| 	SVCB | ||||
| } | ||||
| 
 | ||||
| func (rr *HTTPS) String() string { | ||||
| 	return rr.SVCB.String() | ||||
| } | ||||
| 
 | ||||
| func (rr *HTTPS) parse(c *zlexer, o string) *ParseError { | ||||
| 	return rr.SVCB.parse(c, o) | ||||
| } | ||||
| 
 | ||||
| // SVCBKeyValue defines a key=value pair for the SVCB RR type. | ||||
| // An SVCB RR can have multiple SVCBKeyValues appended to it. | ||||
| type SVCBKeyValue interface { | ||||
| 	Key() SVCBKey          // Key returns the numerical key code. | ||||
| 	pack() ([]byte, error) // pack returns the encoded value. | ||||
| 	unpack([]byte) error   // unpack sets the value. | ||||
| 	String() string        // String returns the string representation of the value. | ||||
| 	parse(string) error    // parse sets the value to the given string representation of the value. | ||||
| 	copy() SVCBKeyValue    // copy returns a deep-copy of the pair. | ||||
| 	len() int              // len returns the length of value in the wire format. | ||||
| } | ||||
| 
 | ||||
| // SVCBMandatory pair adds to required keys that must be interpreted for the RR | ||||
| // to be functional. If ignored, the whole RRSet must be ignored. | ||||
| // "port" and "no-default-alpn" are mandatory by default if present, | ||||
| // so they shouldn't be included here. | ||||
| // | ||||
| // It is incumbent upon the user of this library to reject the RRSet if | ||||
| // or avoid constructing such an RRSet that: | ||||
| // - "mandatory" is included as one of the keys of mandatory | ||||
| // - no key is listed multiple times in mandatory | ||||
| // - all keys listed in mandatory are present | ||||
| // - escape sequences are not used in mandatory | ||||
| // - mandatory, when present, lists at least one key | ||||
| // | ||||
| // Basic use pattern for creating a mandatory option: | ||||
| // | ||||
| //	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}} | ||||
| //	e := new(dns.SVCBMandatory) | ||||
| //	e.Code = []uint16{dns.SVCB_ALPN} | ||||
| //	s.Value = append(s.Value, e) | ||||
| //	t := new(dns.SVCBAlpn) | ||||
| //	t.Alpn = []string{"xmpp-client"} | ||||
| //	s.Value = append(s.Value, t) | ||||
| type SVCBMandatory struct { | ||||
| 	Code []SVCBKey | ||||
| } | ||||
| 
 | ||||
| func (*SVCBMandatory) Key() SVCBKey { return SVCB_MANDATORY } | ||||
| 
 | ||||
| func (s *SVCBMandatory) String() string { | ||||
| 	str := make([]string, len(s.Code)) | ||||
| 	for i, e := range s.Code { | ||||
| 		str[i] = e.String() | ||||
| 	} | ||||
| 	return strings.Join(str, ",") | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBMandatory) pack() ([]byte, error) { | ||||
| 	codes := append([]SVCBKey(nil), s.Code...) | ||||
| 	sort.Slice(codes, func(i, j int) bool { | ||||
| 		return codes[i] < codes[j] | ||||
| 	}) | ||||
| 	b := make([]byte, 2*len(codes)) | ||||
| 	for i, e := range codes { | ||||
| 		binary.BigEndian.PutUint16(b[2*i:], uint16(e)) | ||||
| 	} | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBMandatory) unpack(b []byte) error { | ||||
| 	if len(b)%2 != 0 { | ||||
| 		return errors.New("dns: svcbmandatory: value length is not a multiple of 2") | ||||
| 	} | ||||
| 	codes := make([]SVCBKey, 0, len(b)/2) | ||||
| 	for i := 0; i < len(b); i += 2 { | ||||
| 		// We assume strictly increasing order. | ||||
| 		codes = append(codes, SVCBKey(binary.BigEndian.Uint16(b[i:]))) | ||||
| 	} | ||||
| 	s.Code = codes | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBMandatory) parse(b string) error { | ||||
| 	str := strings.Split(b, ",") | ||||
| 	codes := make([]SVCBKey, 0, len(str)) | ||||
| 	for _, e := range str { | ||||
| 		codes = append(codes, svcbStringToKey(e)) | ||||
| 	} | ||||
| 	s.Code = codes | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBMandatory) len() int { | ||||
| 	return 2 * len(s.Code) | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBMandatory) copy() SVCBKeyValue { | ||||
| 	return &SVCBMandatory{ | ||||
| 		append([]SVCBKey(nil), s.Code...), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SVCBAlpn pair is used to list supported connection protocols. | ||||
| // The user of this library must ensure that at least one protocol is listed when alpn is present. | ||||
| // Protocol IDs can be found at: | ||||
| // https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids | ||||
| // Basic use pattern for creating an alpn option: | ||||
| // | ||||
| //	h := new(dns.HTTPS) | ||||
| //	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET} | ||||
| //	e := new(dns.SVCBAlpn) | ||||
| //	e.Alpn = []string{"h2", "http/1.1"} | ||||
| //	h.Value = append(h.Value, e) | ||||
| type SVCBAlpn struct { | ||||
| 	Alpn []string | ||||
| } | ||||
| 
 | ||||
| func (*SVCBAlpn) Key() SVCBKey { return SVCB_ALPN } | ||||
| 
 | ||||
| func (s *SVCBAlpn) String() string { | ||||
| 	// An ALPN value is a comma-separated list of values, each of which can be | ||||
| 	// an arbitrary binary value. In order to allow parsing, the comma and | ||||
| 	// backslash characters are themselves excaped. | ||||
| 	// | ||||
| 	// However, this escaping is done in addition to the normal escaping which | ||||
| 	// happens in zone files, meaning that these values must be | ||||
| 	// double-escaped. This looks terrible, so if you see a never-ending | ||||
| 	// sequence of backslash in a zone file this may be why. | ||||
| 	// | ||||
| 	// https://datatracker.ietf.org/doc/html/draft-ietf-dnsop-svcb-https-08#appendix-A.1 | ||||
| 	var str strings.Builder | ||||
| 	for i, alpn := range s.Alpn { | ||||
| 		// 4*len(alpn) is the worst case where we escape every character in the alpn as \123, plus 1 byte for the ',' separating the alpn from others | ||||
| 		str.Grow(4*len(alpn) + 1) | ||||
| 		if i > 0 { | ||||
| 			str.WriteByte(',') | ||||
| 		} | ||||
| 		for j := 0; j < len(alpn); j++ { | ||||
| 			e := alpn[j] | ||||
| 			if ' ' > e || e > '~' { | ||||
| 				str.WriteString(escapeByte(e)) | ||||
| 				continue | ||||
| 			} | ||||
| 			switch e { | ||||
| 			// We escape a few characters which may confuse humans or parsers. | ||||
| 			case '"', ';', ' ': | ||||
| 				str.WriteByte('\\') | ||||
| 				str.WriteByte(e) | ||||
| 			// The comma and backslash characters themselves must be | ||||
| 			// doubly-escaped. We use `\\` for the first backslash and | ||||
| 			// the escaped numeric value for the other value. We especially | ||||
| 			// don't want a comma in the output. | ||||
| 			case ',': | ||||
| 				str.WriteString(`\\\044`) | ||||
| 			case '\\': | ||||
| 				str.WriteString(`\\\092`) | ||||
| 			default: | ||||
| 				str.WriteByte(e) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return str.String() | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBAlpn) pack() ([]byte, error) { | ||||
| 	// Liberally estimate the size of an alpn as 10 octets | ||||
| 	b := make([]byte, 0, 10*len(s.Alpn)) | ||||
| 	for _, e := range s.Alpn { | ||||
| 		if e == "" { | ||||
| 			return nil, errors.New("dns: svcbalpn: empty alpn-id") | ||||
| 		} | ||||
| 		if len(e) > 255 { | ||||
| 			return nil, errors.New("dns: svcbalpn: alpn-id too long") | ||||
| 		} | ||||
| 		b = append(b, byte(len(e))) | ||||
| 		b = append(b, e...) | ||||
| 	} | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBAlpn) unpack(b []byte) error { | ||||
| 	// Estimate the size of the smallest alpn as 4 bytes | ||||
| 	alpn := make([]string, 0, len(b)/4) | ||||
| 	for i := 0; i < len(b); { | ||||
| 		length := int(b[i]) | ||||
| 		i++ | ||||
| 		if i+length > len(b) { | ||||
| 			return errors.New("dns: svcbalpn: alpn array overflowing") | ||||
| 		} | ||||
| 		alpn = append(alpn, string(b[i:i+length])) | ||||
| 		i += length | ||||
| 	} | ||||
| 	s.Alpn = alpn | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBAlpn) parse(b string) error { | ||||
| 	if len(b) == 0 { | ||||
| 		s.Alpn = []string{} | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	alpn := []string{} | ||||
| 	a := []byte{} | ||||
| 	for p := 0; p < len(b); { | ||||
| 		c, q := nextByte(b, p) | ||||
| 		if q == 0 { | ||||
| 			return errors.New("dns: svcbalpn: unterminated escape") | ||||
| 		} | ||||
| 		p += q | ||||
| 		// If we find a comma, we have finished reading an alpn. | ||||
| 		if c == ',' { | ||||
| 			if len(a) == 0 { | ||||
| 				return errors.New("dns: svcbalpn: empty protocol identifier") | ||||
| 			} | ||||
| 			alpn = append(alpn, string(a)) | ||||
| 			a = []byte{} | ||||
| 			continue | ||||
| 		} | ||||
| 		// If it's a backslash, we need to handle a comma-separated list. | ||||
| 		if c == '\\' { | ||||
| 			dc, dq := nextByte(b, p) | ||||
| 			if dq == 0 { | ||||
| 				return errors.New("dns: svcbalpn: unterminated escape decoding comma-separated list") | ||||
| 			} | ||||
| 			if dc != '\\' && dc != ',' { | ||||
| 				return errors.New("dns: svcbalpn: bad escaped character decoding comma-separated list") | ||||
| 			} | ||||
| 			p += dq | ||||
| 			c = dc | ||||
| 		} | ||||
| 		a = append(a, c) | ||||
| 	} | ||||
| 	// Add the final alpn. | ||||
| 	if len(a) == 0 { | ||||
| 		return errors.New("dns: svcbalpn: last protocol identifier empty") | ||||
| 	} | ||||
| 	s.Alpn = append(alpn, string(a)) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBAlpn) len() int { | ||||
| 	var l int | ||||
| 	for _, e := range s.Alpn { | ||||
| 		l += 1 + len(e) | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBAlpn) copy() SVCBKeyValue { | ||||
| 	return &SVCBAlpn{ | ||||
| 		append([]string(nil), s.Alpn...), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SVCBNoDefaultAlpn pair signifies no support for default connection protocols. | ||||
| // Should be used in conjunction with alpn. | ||||
| // Basic use pattern for creating a no-default-alpn option: | ||||
| // | ||||
| //	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}} | ||||
| //	t := new(dns.SVCBAlpn) | ||||
| //	t.Alpn = []string{"xmpp-client"} | ||||
| //	s.Value = append(s.Value, t) | ||||
| //	e := new(dns.SVCBNoDefaultAlpn) | ||||
| //	s.Value = append(s.Value, e) | ||||
| type SVCBNoDefaultAlpn struct{} | ||||
| 
 | ||||
| func (*SVCBNoDefaultAlpn) Key() SVCBKey          { return SVCB_NO_DEFAULT_ALPN } | ||||
| func (*SVCBNoDefaultAlpn) copy() SVCBKeyValue    { return &SVCBNoDefaultAlpn{} } | ||||
| func (*SVCBNoDefaultAlpn) pack() ([]byte, error) { return []byte{}, nil } | ||||
| func (*SVCBNoDefaultAlpn) String() string        { return "" } | ||||
| func (*SVCBNoDefaultAlpn) len() int              { return 0 } | ||||
| 
 | ||||
| func (*SVCBNoDefaultAlpn) unpack(b []byte) error { | ||||
| 	if len(b) != 0 { | ||||
| 		return errors.New("dns: svcbnodefaultalpn: no-default-alpn must have no value") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (*SVCBNoDefaultAlpn) parse(b string) error { | ||||
| 	if b != "" { | ||||
| 		return errors.New("dns: svcbnodefaultalpn: no-default-alpn must have no value") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SVCBPort pair defines the port for connection. | ||||
| // Basic use pattern for creating a port option: | ||||
| // | ||||
| //	s := &dns.SVCB{Hdr: dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET}} | ||||
| //	e := new(dns.SVCBPort) | ||||
| //	e.Port = 80 | ||||
| //	s.Value = append(s.Value, e) | ||||
| type SVCBPort struct { | ||||
| 	Port uint16 | ||||
| } | ||||
| 
 | ||||
| func (*SVCBPort) Key() SVCBKey         { return SVCB_PORT } | ||||
| func (*SVCBPort) len() int             { return 2 } | ||||
| func (s *SVCBPort) String() string     { return strconv.FormatUint(uint64(s.Port), 10) } | ||||
| func (s *SVCBPort) copy() SVCBKeyValue { return &SVCBPort{s.Port} } | ||||
| 
 | ||||
| func (s *SVCBPort) unpack(b []byte) error { | ||||
| 	if len(b) != 2 { | ||||
| 		return errors.New("dns: svcbport: port length is not exactly 2 octets") | ||||
| 	} | ||||
| 	s.Port = binary.BigEndian.Uint16(b) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBPort) pack() ([]byte, error) { | ||||
| 	b := make([]byte, 2) | ||||
| 	binary.BigEndian.PutUint16(b, s.Port) | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBPort) parse(b string) error { | ||||
| 	port, err := strconv.ParseUint(b, 10, 16) | ||||
| 	if err != nil { | ||||
| 		return errors.New("dns: svcbport: port out of range") | ||||
| 	} | ||||
| 	s.Port = uint16(port) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SVCBIPv4Hint pair suggests an IPv4 address which may be used to open connections | ||||
| // if A and AAAA record responses for SVCB's Target domain haven't been received. | ||||
| // In that case, optionally, A and AAAA requests can be made, after which the connection | ||||
| // to the hinted IP address may be terminated and a new connection may be opened. | ||||
| // Basic use pattern for creating an ipv4hint option: | ||||
| // | ||||
| //	h := new(dns.HTTPS) | ||||
| //	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET} | ||||
| //	e := new(dns.SVCBIPv4Hint) | ||||
| //	e.Hint = []net.IP{net.IPv4(1,1,1,1).To4()} | ||||
| // | ||||
| //  Or | ||||
| // | ||||
| //	e.Hint = []net.IP{net.ParseIP("1.1.1.1").To4()} | ||||
| //	h.Value = append(h.Value, e) | ||||
| type SVCBIPv4Hint struct { | ||||
| 	Hint []net.IP | ||||
| } | ||||
| 
 | ||||
| func (*SVCBIPv4Hint) Key() SVCBKey { return SVCB_IPV4HINT } | ||||
| func (s *SVCBIPv4Hint) len() int   { return 4 * len(s.Hint) } | ||||
| 
 | ||||
| func (s *SVCBIPv4Hint) pack() ([]byte, error) { | ||||
| 	b := make([]byte, 0, 4*len(s.Hint)) | ||||
| 	for _, e := range s.Hint { | ||||
| 		x := e.To4() | ||||
| 		if x == nil { | ||||
| 			return nil, errors.New("dns: svcbipv4hint: expected ipv4, hint is ipv6") | ||||
| 		} | ||||
| 		b = append(b, x...) | ||||
| 	} | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBIPv4Hint) unpack(b []byte) error { | ||||
| 	if len(b) == 0 || len(b)%4 != 0 { | ||||
| 		return errors.New("dns: svcbipv4hint: ipv4 address byte array length is not a multiple of 4") | ||||
| 	} | ||||
| 	x := make([]net.IP, 0, len(b)/4) | ||||
| 	for i := 0; i < len(b); i += 4 { | ||||
| 		x = append(x, net.IP(b[i:i+4])) | ||||
| 	} | ||||
| 	s.Hint = x | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBIPv4Hint) String() string { | ||||
| 	str := make([]string, len(s.Hint)) | ||||
| 	for i, e := range s.Hint { | ||||
| 		x := e.To4() | ||||
| 		if x == nil { | ||||
| 			return "<nil>" | ||||
| 		} | ||||
| 		str[i] = x.String() | ||||
| 	} | ||||
| 	return strings.Join(str, ",") | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBIPv4Hint) parse(b string) error { | ||||
| 	if strings.Contains(b, ":") { | ||||
| 		return errors.New("dns: svcbipv4hint: expected ipv4, got ipv6") | ||||
| 	} | ||||
| 	str := strings.Split(b, ",") | ||||
| 	dst := make([]net.IP, len(str)) | ||||
| 	for i, e := range str { | ||||
| 		ip := net.ParseIP(e).To4() | ||||
| 		if ip == nil { | ||||
| 			return errors.New("dns: svcbipv4hint: bad ip") | ||||
| 		} | ||||
| 		dst[i] = ip | ||||
| 	} | ||||
| 	s.Hint = dst | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBIPv4Hint) copy() SVCBKeyValue { | ||||
| 	hint := make([]net.IP, len(s.Hint)) | ||||
| 	for i, ip := range s.Hint { | ||||
| 		hint[i] = copyIP(ip) | ||||
| 	} | ||||
| 
 | ||||
| 	return &SVCBIPv4Hint{ | ||||
| 		Hint: hint, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SVCBECHConfig pair contains the ECHConfig structure defined in draft-ietf-tls-esni [RFC xxxx]. | ||||
| // Basic use pattern for creating an ech option: | ||||
| // | ||||
| //	h := new(dns.HTTPS) | ||||
| //	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET} | ||||
| //	e := new(dns.SVCBECHConfig) | ||||
| //	e.ECH = []byte{0xfe, 0x08, ...} | ||||
| //	h.Value = append(h.Value, e) | ||||
| type SVCBECHConfig struct { | ||||
| 	ECH []byte // Specifically ECHConfigList including the redundant length prefix | ||||
| } | ||||
| 
 | ||||
| func (*SVCBECHConfig) Key() SVCBKey     { return SVCB_ECHCONFIG } | ||||
| func (s *SVCBECHConfig) String() string { return toBase64(s.ECH) } | ||||
| func (s *SVCBECHConfig) len() int       { return len(s.ECH) } | ||||
| 
 | ||||
| func (s *SVCBECHConfig) pack() ([]byte, error) { | ||||
| 	return append([]byte(nil), s.ECH...), nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBECHConfig) copy() SVCBKeyValue { | ||||
| 	return &SVCBECHConfig{ | ||||
| 		append([]byte(nil), s.ECH...), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBECHConfig) unpack(b []byte) error { | ||||
| 	s.ECH = append([]byte(nil), b...) | ||||
| 	return nil | ||||
| } | ||||
| func (s *SVCBECHConfig) parse(b string) error { | ||||
| 	x, err := fromBase64([]byte(b)) | ||||
| 	if err != nil { | ||||
| 		return errors.New("dns: svcbech: bad base64 ech") | ||||
| 	} | ||||
| 	s.ECH = x | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // SVCBIPv6Hint pair suggests an IPv6 address which may be used to open connections | ||||
| // if A and AAAA record responses for SVCB's Target domain haven't been received. | ||||
| // In that case, optionally, A and AAAA requests can be made, after which the | ||||
| // connection to the hinted IP address may be terminated and a new connection may be opened. | ||||
| // Basic use pattern for creating an ipv6hint option: | ||||
| // | ||||
| //	h := new(dns.HTTPS) | ||||
| //	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET} | ||||
| //	e := new(dns.SVCBIPv6Hint) | ||||
| //	e.Hint = []net.IP{net.ParseIP("2001:db8::1")} | ||||
| //	h.Value = append(h.Value, e) | ||||
| type SVCBIPv6Hint struct { | ||||
| 	Hint []net.IP | ||||
| } | ||||
| 
 | ||||
| func (*SVCBIPv6Hint) Key() SVCBKey { return SVCB_IPV6HINT } | ||||
| func (s *SVCBIPv6Hint) len() int   { return 16 * len(s.Hint) } | ||||
| 
 | ||||
| func (s *SVCBIPv6Hint) pack() ([]byte, error) { | ||||
| 	b := make([]byte, 0, 16*len(s.Hint)) | ||||
| 	for _, e := range s.Hint { | ||||
| 		if len(e) != net.IPv6len || e.To4() != nil { | ||||
| 			return nil, errors.New("dns: svcbipv6hint: expected ipv6, hint is ipv4") | ||||
| 		} | ||||
| 		b = append(b, e...) | ||||
| 	} | ||||
| 	return b, nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBIPv6Hint) unpack(b []byte) error { | ||||
| 	if len(b) == 0 || len(b)%16 != 0 { | ||||
| 		return errors.New("dns: svcbipv6hint: ipv6 address byte array length not a multiple of 16") | ||||
| 	} | ||||
| 	x := make([]net.IP, 0, len(b)/16) | ||||
| 	for i := 0; i < len(b); i += 16 { | ||||
| 		ip := net.IP(b[i : i+16]) | ||||
| 		if ip.To4() != nil { | ||||
| 			return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4") | ||||
| 		} | ||||
| 		x = append(x, ip) | ||||
| 	} | ||||
| 	s.Hint = x | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBIPv6Hint) String() string { | ||||
| 	str := make([]string, len(s.Hint)) | ||||
| 	for i, e := range s.Hint { | ||||
| 		if x := e.To4(); x != nil { | ||||
| 			return "<nil>" | ||||
| 		} | ||||
| 		str[i] = e.String() | ||||
| 	} | ||||
| 	return strings.Join(str, ",") | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBIPv6Hint) parse(b string) error { | ||||
| 	str := strings.Split(b, ",") | ||||
| 	dst := make([]net.IP, len(str)) | ||||
| 	for i, e := range str { | ||||
| 		ip := net.ParseIP(e) | ||||
| 		if ip == nil { | ||||
| 			return errors.New("dns: svcbipv6hint: bad ip") | ||||
| 		} | ||||
| 		if ip.To4() != nil { | ||||
| 			return errors.New("dns: svcbipv6hint: expected ipv6, got ipv4-mapped-ipv6") | ||||
| 		} | ||||
| 		dst[i] = ip | ||||
| 	} | ||||
| 	s.Hint = dst | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBIPv6Hint) copy() SVCBKeyValue { | ||||
| 	hint := make([]net.IP, len(s.Hint)) | ||||
| 	for i, ip := range s.Hint { | ||||
| 		hint[i] = copyIP(ip) | ||||
| 	} | ||||
| 
 | ||||
| 	return &SVCBIPv6Hint{ | ||||
| 		Hint: hint, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SVCBDoHPath pair is used to indicate the URI template that the | ||||
| // clients may use to construct a DNS over HTTPS URI. | ||||
| // | ||||
| // See RFC xxxx (https://datatracker.ietf.org/doc/html/draft-ietf-add-svcb-dns-02) | ||||
| // and RFC yyyy (https://datatracker.ietf.org/doc/html/draft-ietf-add-ddr-06). | ||||
| // | ||||
| // A basic example of using the dohpath option together with the alpn | ||||
| // option to indicate support for DNS over HTTPS on a certain path: | ||||
| // | ||||
| //	s := new(dns.SVCB) | ||||
| //	s.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeSVCB, Class: dns.ClassINET} | ||||
| //	e := new(dns.SVCBAlpn) | ||||
| //	e.Alpn = []string{"h2", "h3"} | ||||
| //	p := new(dns.SVCBDoHPath) | ||||
| //	p.Template = "/dns-query{?dns}" | ||||
| //	s.Value = append(s.Value, e, p) | ||||
| // | ||||
| // The parsing currently doesn't validate that Template is a valid | ||||
| // RFC 6570 URI template. | ||||
| type SVCBDoHPath struct { | ||||
| 	Template string | ||||
| } | ||||
| 
 | ||||
| func (*SVCBDoHPath) Key() SVCBKey            { return SVCB_DOHPATH } | ||||
| func (s *SVCBDoHPath) String() string        { return svcbParamToStr([]byte(s.Template)) } | ||||
| func (s *SVCBDoHPath) len() int              { return len(s.Template) } | ||||
| func (s *SVCBDoHPath) pack() ([]byte, error) { return []byte(s.Template), nil } | ||||
| 
 | ||||
| func (s *SVCBDoHPath) unpack(b []byte) error { | ||||
| 	s.Template = string(b) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBDoHPath) parse(b string) error { | ||||
| 	template, err := svcbParseParam(b) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("dns: svcbdohpath: %w", err) | ||||
| 	} | ||||
| 	s.Template = string(template) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBDoHPath) copy() SVCBKeyValue { | ||||
| 	return &SVCBDoHPath{ | ||||
| 		Template: s.Template, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // SVCBLocal pair is intended for experimental/private use. The key is recommended | ||||
| // to be in the range [SVCB_PRIVATE_LOWER, SVCB_PRIVATE_UPPER]. | ||||
| // Basic use pattern for creating a keyNNNNN option: | ||||
| // | ||||
| //	h := new(dns.HTTPS) | ||||
| //	h.Hdr = dns.RR_Header{Name: ".", Rrtype: dns.TypeHTTPS, Class: dns.ClassINET} | ||||
| //	e := new(dns.SVCBLocal) | ||||
| //	e.KeyCode = 65400 | ||||
| //	e.Data = []byte("abc") | ||||
| //	h.Value = append(h.Value, e) | ||||
| type SVCBLocal struct { | ||||
| 	KeyCode SVCBKey // Never 65535 or any assigned keys. | ||||
| 	Data    []byte  // All byte sequences are allowed. | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBLocal) Key() SVCBKey          { return s.KeyCode } | ||||
| func (s *SVCBLocal) String() string        { return svcbParamToStr(s.Data) } | ||||
| func (s *SVCBLocal) pack() ([]byte, error) { return append([]byte(nil), s.Data...), nil } | ||||
| func (s *SVCBLocal) len() int              { return len(s.Data) } | ||||
| 
 | ||||
| func (s *SVCBLocal) unpack(b []byte) error { | ||||
| 	s.Data = append([]byte(nil), b...) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBLocal) parse(b string) error { | ||||
| 	data, err := svcbParseParam(b) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("dns: svcblocal: svcb private/experimental key %w", err) | ||||
| 	} | ||||
| 	s.Data = data | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| func (s *SVCBLocal) copy() SVCBKeyValue { | ||||
| 	return &SVCBLocal{s.KeyCode, | ||||
| 		append([]byte(nil), s.Data...), | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (rr *SVCB) String() string { | ||||
| 	s := rr.Hdr.String() + | ||||
| 		strconv.Itoa(int(rr.Priority)) + " " + | ||||
| 		sprintName(rr.Target) | ||||
| 	for _, e := range rr.Value { | ||||
| 		s += " " + e.Key().String() + "=\"" + e.String() + "\"" | ||||
| 	} | ||||
| 	return s | ||||
| } | ||||
| 
 | ||||
| // areSVCBPairArraysEqual checks if SVCBKeyValue arrays are equal after sorting their | ||||
| // copies. arrA and arrB have equal lengths, otherwise zduplicate.go wouldn't call this function. | ||||
| func areSVCBPairArraysEqual(a []SVCBKeyValue, b []SVCBKeyValue) bool { | ||||
| 	a = append([]SVCBKeyValue(nil), a...) | ||||
| 	b = append([]SVCBKeyValue(nil), b...) | ||||
| 	sort.Slice(a, func(i, j int) bool { return a[i].Key() < a[j].Key() }) | ||||
| 	sort.Slice(b, func(i, j int) bool { return b[i].Key() < b[j].Key() }) | ||||
| 	for i, e := range a { | ||||
| 		if e.Key() != b[i].Key() { | ||||
| 			return false | ||||
| 		} | ||||
| 		b1, err1 := e.pack() | ||||
| 		b2, err2 := b[i].pack() | ||||
| 		if err1 != nil || err2 != nil || !bytes.Equal(b1, b2) { | ||||
| 			return false | ||||
| 		} | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
| 
 | ||||
| // svcbParamStr converts the value of an SVCB parameter into a DNS presentation-format string. | ||||
| func svcbParamToStr(s []byte) string { | ||||
| 	var str strings.Builder | ||||
| 	str.Grow(4 * len(s)) | ||||
| 	for _, e := range s { | ||||
| 		if ' ' <= e && e <= '~' { | ||||
| 			switch e { | ||||
| 			case '"', ';', ' ', '\\': | ||||
| 				str.WriteByte('\\') | ||||
| 				str.WriteByte(e) | ||||
| 			default: | ||||
| 				str.WriteByte(e) | ||||
| 			} | ||||
| 		} else { | ||||
| 			str.WriteString(escapeByte(e)) | ||||
| 		} | ||||
| 	} | ||||
| 	return str.String() | ||||
| } | ||||
| 
 | ||||
| // svcbParseParam parses a DNS presentation-format string into an SVCB parameter value. | ||||
| func svcbParseParam(b string) ([]byte, error) { | ||||
| 	data := make([]byte, 0, len(b)) | ||||
| 	for i := 0; i < len(b); { | ||||
| 		if b[i] != '\\' { | ||||
| 			data = append(data, b[i]) | ||||
| 			i++ | ||||
| 			continue | ||||
| 		} | ||||
| 		if i+1 == len(b) { | ||||
| 			return nil, errors.New("escape unterminated") | ||||
| 		} | ||||
| 		if isDigit(b[i+1]) { | ||||
| 			if i+3 < len(b) && isDigit(b[i+2]) && isDigit(b[i+3]) { | ||||
| 				a, err := strconv.ParseUint(b[i+1:i+4], 10, 8) | ||||
| 				if err == nil { | ||||
| 					i += 4 | ||||
| 					data = append(data, byte(a)) | ||||
| 					continue | ||||
| 				} | ||||
| 			} | ||||
| 			return nil, errors.New("bad escaped octet") | ||||
| 		} else { | ||||
| 			data = append(data, b[i+1]) | ||||
| 			i += 2 | ||||
| 		} | ||||
| 	} | ||||
| 	return data, nil | ||||
| } | ||||
							
								
								
									
										44
									
								
								vendor/github.com/miekg/dns/tlsa.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/miekg/dns/tlsa.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/x509" | ||||
| 	"net" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| // Sign creates a TLSA record from an SSL certificate. | ||||
| func (r *TLSA) Sign(usage, selector, matchingType int, cert *x509.Certificate) (err error) { | ||||
| 	r.Hdr.Rrtype = TypeTLSA | ||||
| 	r.Usage = uint8(usage) | ||||
| 	r.Selector = uint8(selector) | ||||
| 	r.MatchingType = uint8(matchingType) | ||||
| 
 | ||||
| 	r.Certificate, err = CertificateToDANE(r.Selector, r.MatchingType, cert) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // Verify verifies a TLSA record against an SSL certificate. If it is OK | ||||
| // a nil error is returned. | ||||
| func (r *TLSA) Verify(cert *x509.Certificate) error { | ||||
| 	c, err := CertificateToDANE(r.Selector, r.MatchingType, cert) | ||||
| 	if err != nil { | ||||
| 		return err // Not also ErrSig? | ||||
| 	} | ||||
| 	if r.Certificate == c { | ||||
| 		return nil | ||||
| 	} | ||||
| 	return ErrSig // ErrSig, really? | ||||
| } | ||||
| 
 | ||||
| // TLSAName returns the ownername of a TLSA resource record as per the | ||||
| // rules specified in RFC 6698, Section 3. | ||||
| func TLSAName(name, service, network string) (string, error) { | ||||
| 	if !IsFqdn(name) { | ||||
| 		return "", ErrFqdn | ||||
| 	} | ||||
| 	p, err := net.LookupPort(network, service) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return "_" + strconv.Itoa(p) + "._" + network + "." + name, nil | ||||
| } | ||||
							
								
								
									
										9
									
								
								vendor/github.com/miekg/dns/tools.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								vendor/github.com/miekg/dns/tools.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| // +build tools | ||||
| 
 | ||||
| // We include our tool dependencies for `go generate` here to ensure they're | ||||
| // properly tracked by the go tool. See the Go Wiki for the rationale behind this: | ||||
| // https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module. | ||||
| 
 | ||||
| package dns | ||||
| 
 | ||||
| import _ "golang.org/x/tools/go/packages" | ||||
							
								
								
									
										456
									
								
								vendor/github.com/miekg/dns/tsig.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										456
									
								
								vendor/github.com/miekg/dns/tsig.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,456 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto/hmac" | ||||
| 	"crypto/sha1" | ||||
| 	"crypto/sha256" | ||||
| 	"crypto/sha512" | ||||
| 	"encoding/binary" | ||||
| 	"encoding/hex" | ||||
| 	"hash" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // HMAC hashing codes. These are transmitted as domain names. | ||||
| const ( | ||||
| 	HmacSHA1   = "hmac-sha1." | ||||
| 	HmacSHA224 = "hmac-sha224." | ||||
| 	HmacSHA256 = "hmac-sha256." | ||||
| 	HmacSHA384 = "hmac-sha384." | ||||
| 	HmacSHA512 = "hmac-sha512." | ||||
| 
 | ||||
| 	HmacMD5 = "hmac-md5.sig-alg.reg.int." // Deprecated: HmacMD5 is no longer supported. | ||||
| ) | ||||
| 
 | ||||
| // TsigProvider provides the API to plug-in a custom TSIG implementation. | ||||
| type TsigProvider interface { | ||||
| 	// Generate is passed the DNS message to be signed and the partial TSIG RR. It returns the signature and nil, otherwise an error. | ||||
| 	Generate(msg []byte, t *TSIG) ([]byte, error) | ||||
| 	// Verify is passed the DNS message to be verified and the TSIG RR. If the signature is valid it will return nil, otherwise an error. | ||||
| 	Verify(msg []byte, t *TSIG) error | ||||
| } | ||||
| 
 | ||||
| type tsigHMACProvider string | ||||
| 
 | ||||
| func (key tsigHMACProvider) Generate(msg []byte, t *TSIG) ([]byte, error) { | ||||
| 	// If we barf here, the caller is to blame | ||||
| 	rawsecret, err := fromBase64([]byte(key)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var h hash.Hash | ||||
| 	switch CanonicalName(t.Algorithm) { | ||||
| 	case HmacSHA1: | ||||
| 		h = hmac.New(sha1.New, rawsecret) | ||||
| 	case HmacSHA224: | ||||
| 		h = hmac.New(sha256.New224, rawsecret) | ||||
| 	case HmacSHA256: | ||||
| 		h = hmac.New(sha256.New, rawsecret) | ||||
| 	case HmacSHA384: | ||||
| 		h = hmac.New(sha512.New384, rawsecret) | ||||
| 	case HmacSHA512: | ||||
| 		h = hmac.New(sha512.New, rawsecret) | ||||
| 	default: | ||||
| 		return nil, ErrKeyAlg | ||||
| 	} | ||||
| 	h.Write(msg) | ||||
| 	return h.Sum(nil), nil | ||||
| } | ||||
| 
 | ||||
| func (key tsigHMACProvider) Verify(msg []byte, t *TSIG) error { | ||||
| 	b, err := key.Generate(msg, t) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	mac, err := hex.DecodeString(t.MAC) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if !hmac.Equal(b, mac) { | ||||
| 		return ErrSig | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| type tsigSecretProvider map[string]string | ||||
| 
 | ||||
| func (ts tsigSecretProvider) Generate(msg []byte, t *TSIG) ([]byte, error) { | ||||
| 	key, ok := ts[t.Hdr.Name] | ||||
| 	if !ok { | ||||
| 		return nil, ErrSecret | ||||
| 	} | ||||
| 	return tsigHMACProvider(key).Generate(msg, t) | ||||
| } | ||||
| 
 | ||||
| func (ts tsigSecretProvider) Verify(msg []byte, t *TSIG) error { | ||||
| 	key, ok := ts[t.Hdr.Name] | ||||
| 	if !ok { | ||||
| 		return ErrSecret | ||||
| 	} | ||||
| 	return tsigHMACProvider(key).Verify(msg, t) | ||||
| } | ||||
| 
 | ||||
| // TSIG is the RR the holds the transaction signature of a message. | ||||
| // See RFC 2845 and RFC 4635. | ||||
| type TSIG struct { | ||||
| 	Hdr        RR_Header | ||||
| 	Algorithm  string `dns:"domain-name"` | ||||
| 	TimeSigned uint64 `dns:"uint48"` | ||||
| 	Fudge      uint16 | ||||
| 	MACSize    uint16 | ||||
| 	MAC        string `dns:"size-hex:MACSize"` | ||||
| 	OrigId     uint16 | ||||
| 	Error      uint16 | ||||
| 	OtherLen   uint16 | ||||
| 	OtherData  string `dns:"size-hex:OtherLen"` | ||||
| } | ||||
| 
 | ||||
| // TSIG has no official presentation format, but this will suffice. | ||||
| 
 | ||||
| func (rr *TSIG) String() string { | ||||
| 	s := "\n;; TSIG PSEUDOSECTION:\n; " // add another semi-colon to signify TSIG does not have a presentation format | ||||
| 	s += rr.Hdr.String() + | ||||
| 		" " + rr.Algorithm + | ||||
| 		" " + tsigTimeToString(rr.TimeSigned) + | ||||
| 		" " + strconv.Itoa(int(rr.Fudge)) + | ||||
| 		" " + strconv.Itoa(int(rr.MACSize)) + | ||||
| 		" " + strings.ToUpper(rr.MAC) + | ||||
| 		" " + strconv.Itoa(int(rr.OrigId)) + | ||||
| 		" " + strconv.Itoa(int(rr.Error)) + // BIND prints NOERROR | ||||
| 		" " + strconv.Itoa(int(rr.OtherLen)) + | ||||
| 		" " + rr.OtherData | ||||
| 	return s | ||||
| } | ||||
| 
 | ||||
| func (*TSIG) parse(c *zlexer, origin string) *ParseError { | ||||
| 	return &ParseError{err: "TSIG records do not have a presentation format"} | ||||
| } | ||||
| 
 | ||||
| // The following values must be put in wireformat, so that the MAC can be calculated. | ||||
| // RFC 2845, section 3.4.2. TSIG Variables. | ||||
| type tsigWireFmt struct { | ||||
| 	// From RR_Header | ||||
| 	Name  string `dns:"domain-name"` | ||||
| 	Class uint16 | ||||
| 	Ttl   uint32 | ||||
| 	// Rdata of the TSIG | ||||
| 	Algorithm  string `dns:"domain-name"` | ||||
| 	TimeSigned uint64 `dns:"uint48"` | ||||
| 	Fudge      uint16 | ||||
| 	// MACSize, MAC and OrigId excluded | ||||
| 	Error     uint16 | ||||
| 	OtherLen  uint16 | ||||
| 	OtherData string `dns:"size-hex:OtherLen"` | ||||
| } | ||||
| 
 | ||||
| // If we have the MAC use this type to convert it to wiredata. Section 3.4.3. Request MAC | ||||
| type macWireFmt struct { | ||||
| 	MACSize uint16 | ||||
| 	MAC     string `dns:"size-hex:MACSize"` | ||||
| } | ||||
| 
 | ||||
| // 3.3. Time values used in TSIG calculations | ||||
| type timerWireFmt struct { | ||||
| 	TimeSigned uint64 `dns:"uint48"` | ||||
| 	Fudge      uint16 | ||||
| } | ||||
| 
 | ||||
| // TsigGenerate fills out the TSIG record attached to the message. | ||||
| // The message should contain | ||||
| // a "stub" TSIG RR with the algorithm, key name (owner name of the RR), | ||||
| // time fudge (defaults to 300 seconds) and the current time | ||||
| // The TSIG MAC is saved in that Tsig RR. | ||||
| // When TsigGenerate is called for the first time requestMAC is set to the empty string and | ||||
| // timersOnly is false. | ||||
| // If something goes wrong an error is returned, otherwise it is nil. | ||||
| func TsigGenerate(m *Msg, secret, requestMAC string, timersOnly bool) ([]byte, string, error) { | ||||
| 	return tsigGenerateProvider(m, tsigHMACProvider(secret), requestMAC, timersOnly) | ||||
| } | ||||
| 
 | ||||
| func tsigGenerateProvider(m *Msg, provider TsigProvider, requestMAC string, timersOnly bool) ([]byte, string, error) { | ||||
| 	if m.IsTsig() == nil { | ||||
| 		panic("dns: TSIG not last RR in additional") | ||||
| 	} | ||||
| 
 | ||||
| 	rr := m.Extra[len(m.Extra)-1].(*TSIG) | ||||
| 	m.Extra = m.Extra[0 : len(m.Extra)-1] // kill the TSIG from the msg | ||||
| 	mbuf, err := m.Pack() | ||||
| 	if err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 
 | ||||
| 	buf, err := tsigBuffer(mbuf, rr, requestMAC, timersOnly) | ||||
| 	if err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 
 | ||||
| 	t := new(TSIG) | ||||
| 	// Copy all TSIG fields except MAC, its size, and time signed which are filled when signing. | ||||
| 	*t = *rr | ||||
| 	t.TimeSigned = 0 | ||||
| 	t.MAC = "" | ||||
| 	t.MACSize = 0 | ||||
| 
 | ||||
| 	// Sign unless there is a key or MAC validation error (RFC 8945 5.3.2) | ||||
| 	if rr.Error != RcodeBadKey && rr.Error != RcodeBadSig { | ||||
| 		mac, err := provider.Generate(buf, rr) | ||||
| 		if err != nil { | ||||
| 			return nil, "", err | ||||
| 		} | ||||
| 		t.TimeSigned = rr.TimeSigned | ||||
| 		t.MAC = hex.EncodeToString(mac) | ||||
| 		t.MACSize = uint16(len(t.MAC) / 2) // Size is half! | ||||
| 	} | ||||
| 
 | ||||
| 	tbuf := make([]byte, Len(t)) | ||||
| 	off, err := PackRR(t, tbuf, 0, nil, false) | ||||
| 	if err != nil { | ||||
| 		return nil, "", err | ||||
| 	} | ||||
| 	mbuf = append(mbuf, tbuf[:off]...) | ||||
| 	// Update the ArCount directly in the buffer. | ||||
| 	binary.BigEndian.PutUint16(mbuf[10:], uint16(len(m.Extra)+1)) | ||||
| 
 | ||||
| 	return mbuf, t.MAC, nil | ||||
| } | ||||
| 
 | ||||
| // TsigVerify verifies the TSIG on a message. | ||||
| // If the signature does not validate err contains the | ||||
| // error, otherwise it is nil. | ||||
| func TsigVerify(msg []byte, secret, requestMAC string, timersOnly bool) error { | ||||
| 	return tsigVerify(msg, tsigHMACProvider(secret), requestMAC, timersOnly, uint64(time.Now().Unix())) | ||||
| } | ||||
| 
 | ||||
| func tsigVerifyProvider(msg []byte, provider TsigProvider, requestMAC string, timersOnly bool) error { | ||||
| 	return tsigVerify(msg, provider, requestMAC, timersOnly, uint64(time.Now().Unix())) | ||||
| } | ||||
| 
 | ||||
| // actual implementation of TsigVerify, taking the current time ('now') as a parameter for the convenience of tests. | ||||
| func tsigVerify(msg []byte, provider TsigProvider, requestMAC string, timersOnly bool, now uint64) error { | ||||
| 	// Strip the TSIG from the incoming msg | ||||
| 	stripped, tsig, err := stripTsig(msg) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	buf, err := tsigBuffer(stripped, tsig, requestMAC, timersOnly) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	if err := provider.Verify(buf, tsig); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// Fudge factor works both ways. A message can arrive before it was signed because | ||||
| 	// of clock skew. | ||||
| 	// We check this after verifying the signature, following draft-ietf-dnsop-rfc2845bis | ||||
| 	// instead of RFC2845, in order to prevent a security vulnerability as reported in CVE-2017-3142/3143. | ||||
| 	ti := now - tsig.TimeSigned | ||||
| 	if now < tsig.TimeSigned { | ||||
| 		ti = tsig.TimeSigned - now | ||||
| 	} | ||||
| 	if uint64(tsig.Fudge) < ti { | ||||
| 		return ErrTime | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // Create a wiredata buffer for the MAC calculation. | ||||
| func tsigBuffer(msgbuf []byte, rr *TSIG, requestMAC string, timersOnly bool) ([]byte, error) { | ||||
| 	var buf []byte | ||||
| 	if rr.TimeSigned == 0 { | ||||
| 		rr.TimeSigned = uint64(time.Now().Unix()) | ||||
| 	} | ||||
| 	if rr.Fudge == 0 { | ||||
| 		rr.Fudge = 300 // Standard (RFC) default. | ||||
| 	} | ||||
| 
 | ||||
| 	// Replace message ID in header with original ID from TSIG | ||||
| 	binary.BigEndian.PutUint16(msgbuf[0:2], rr.OrigId) | ||||
| 
 | ||||
| 	if requestMAC != "" { | ||||
| 		m := new(macWireFmt) | ||||
| 		m.MACSize = uint16(len(requestMAC) / 2) | ||||
| 		m.MAC = requestMAC | ||||
| 		buf = make([]byte, len(requestMAC)) // long enough | ||||
| 		n, err := packMacWire(m, buf) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		buf = buf[:n] | ||||
| 	} | ||||
| 
 | ||||
| 	tsigvar := make([]byte, DefaultMsgSize) | ||||
| 	if timersOnly { | ||||
| 		tsig := new(timerWireFmt) | ||||
| 		tsig.TimeSigned = rr.TimeSigned | ||||
| 		tsig.Fudge = rr.Fudge | ||||
| 		n, err := packTimerWire(tsig, tsigvar) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		tsigvar = tsigvar[:n] | ||||
| 	} else { | ||||
| 		tsig := new(tsigWireFmt) | ||||
| 		tsig.Name = CanonicalName(rr.Hdr.Name) | ||||
| 		tsig.Class = ClassANY | ||||
| 		tsig.Ttl = rr.Hdr.Ttl | ||||
| 		tsig.Algorithm = CanonicalName(rr.Algorithm) | ||||
| 		tsig.TimeSigned = rr.TimeSigned | ||||
| 		tsig.Fudge = rr.Fudge | ||||
| 		tsig.Error = rr.Error | ||||
| 		tsig.OtherLen = rr.OtherLen | ||||
| 		tsig.OtherData = rr.OtherData | ||||
| 		n, err := packTsigWire(tsig, tsigvar) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		tsigvar = tsigvar[:n] | ||||
| 	} | ||||
| 
 | ||||
| 	if requestMAC != "" { | ||||
| 		x := append(buf, msgbuf...) | ||||
| 		buf = append(x, tsigvar...) | ||||
| 	} else { | ||||
| 		buf = append(msgbuf, tsigvar...) | ||||
| 	} | ||||
| 	return buf, nil | ||||
| } | ||||
| 
 | ||||
| // Strip the TSIG from the raw message. | ||||
| func stripTsig(msg []byte) ([]byte, *TSIG, error) { | ||||
| 	// Copied from msg.go's Unpack() Header, but modified. | ||||
| 	var ( | ||||
| 		dh  Header | ||||
| 		err error | ||||
| 	) | ||||
| 	off, tsigoff := 0, 0 | ||||
| 
 | ||||
| 	if dh, off, err = unpackMsgHdr(msg, off); err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	if dh.Arcount == 0 { | ||||
| 		return nil, nil, ErrNoSig | ||||
| 	} | ||||
| 
 | ||||
| 	// Rcode, see msg.go Unpack() | ||||
| 	if int(dh.Bits&0xF) == RcodeNotAuth { | ||||
| 		return nil, nil, ErrAuth | ||||
| 	} | ||||
| 
 | ||||
| 	for i := 0; i < int(dh.Qdcount); i++ { | ||||
| 		_, off, err = unpackQuestion(msg, off) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	_, off, err = unpackRRslice(int(dh.Ancount), msg, off) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 	_, off, err = unpackRRslice(int(dh.Nscount), msg, off) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	rr := new(TSIG) | ||||
| 	var extra RR | ||||
| 	for i := 0; i < int(dh.Arcount); i++ { | ||||
| 		tsigoff = off | ||||
| 		extra, off, err = UnpackRR(msg, off) | ||||
| 		if err != nil { | ||||
| 			return nil, nil, err | ||||
| 		} | ||||
| 		if extra.Header().Rrtype == TypeTSIG { | ||||
| 			rr = extra.(*TSIG) | ||||
| 			// Adjust Arcount. | ||||
| 			arcount := binary.BigEndian.Uint16(msg[10:]) | ||||
| 			binary.BigEndian.PutUint16(msg[10:], arcount-1) | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	if rr == nil { | ||||
| 		return nil, nil, ErrNoSig | ||||
| 	} | ||||
| 	return msg[:tsigoff], rr, nil | ||||
| } | ||||
| 
 | ||||
| // Translate the TSIG time signed into a date. There is no | ||||
| // need for RFC1982 calculations as this date is 48 bits. | ||||
| func tsigTimeToString(t uint64) string { | ||||
| 	ti := time.Unix(int64(t), 0).UTC() | ||||
| 	return ti.Format("20060102150405") | ||||
| } | ||||
| 
 | ||||
| func packTsigWire(tw *tsigWireFmt, msg []byte) (int, error) { | ||||
| 	// copied from zmsg.go TSIG packing | ||||
| 	// RR_Header | ||||
| 	off, err := PackDomainName(tw.Name, msg, 0, nil, false) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint16(tw.Class, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint32(tw.Ttl, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 
 | ||||
| 	off, err = PackDomainName(tw.Algorithm, msg, off, nil, false) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint48(tw.TimeSigned, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint16(tw.Fudge, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 
 | ||||
| 	off, err = packUint16(tw.Error, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint16(tw.OtherLen, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packStringHex(tw.OtherData, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func packMacWire(mw *macWireFmt, msg []byte) (int, error) { | ||||
| 	off, err := packUint16(mw.MACSize, msg, 0) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packStringHex(mw.MAC, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
| 
 | ||||
| func packTimerWire(tw *timerWireFmt, msg []byte) (int, error) { | ||||
| 	off, err := packUint48(tw.TimeSigned, msg, 0) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	off, err = packUint16(tw.Fudge, msg, off) | ||||
| 	if err != nil { | ||||
| 		return off, err | ||||
| 	} | ||||
| 	return off, nil | ||||
| } | ||||
							
								
								
									
										1559
									
								
								vendor/github.com/miekg/dns/types.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1559
									
								
								vendor/github.com/miekg/dns/types.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										102
									
								
								vendor/github.com/miekg/dns/udp.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								vendor/github.com/miekg/dns/udp.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,102 @@ | |||
| // +build !windows | ||||
| 
 | ||||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"net" | ||||
| 
 | ||||
| 	"golang.org/x/net/ipv4" | ||||
| 	"golang.org/x/net/ipv6" | ||||
| ) | ||||
| 
 | ||||
| // This is the required size of the OOB buffer to pass to ReadMsgUDP. | ||||
| var udpOOBSize = func() int { | ||||
| 	// We can't know whether we'll get an IPv4 control message or an | ||||
| 	// IPv6 control message ahead of time. To get around this, we size | ||||
| 	// the buffer equal to the largest of the two. | ||||
| 
 | ||||
| 	oob4 := ipv4.NewControlMessage(ipv4.FlagDst | ipv4.FlagInterface) | ||||
| 	oob6 := ipv6.NewControlMessage(ipv6.FlagDst | ipv6.FlagInterface) | ||||
| 
 | ||||
| 	if len(oob4) > len(oob6) { | ||||
| 		return len(oob4) | ||||
| 	} | ||||
| 
 | ||||
| 	return len(oob6) | ||||
| }() | ||||
| 
 | ||||
| // SessionUDP holds the remote address and the associated | ||||
| // out-of-band data. | ||||
| type SessionUDP struct { | ||||
| 	raddr   *net.UDPAddr | ||||
| 	context []byte | ||||
| } | ||||
| 
 | ||||
| // RemoteAddr returns the remote network address. | ||||
| 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. | ||||
| func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) { | ||||
| 	oob := make([]byte, udpOOBSize) | ||||
| 	n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob) | ||||
| 	if err != nil { | ||||
| 		return n, nil, err | ||||
| 	} | ||||
| 	return n, &SessionUDP{raddr, oob[:oobn]}, err | ||||
| } | ||||
| 
 | ||||
| // WriteToSessionUDP acts just like net.UDPConn.WriteTo(), but uses a *SessionUDP instead of a net.Addr. | ||||
| func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) { | ||||
| 	oob := correctSource(session.context) | ||||
| 	n, _, err := conn.WriteMsgUDP(b, oob, session.raddr) | ||||
| 	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. | ||||
| 	cm6 := new(ipv6.ControlMessage) | ||||
| 	if cm6.Parse(oob) == nil && cm6.Dst != nil { | ||||
| 		return cm6.Dst | ||||
| 	} | ||||
| 	cm4 := new(ipv4.ControlMessage) | ||||
| 	if cm4.Parse(oob) == nil && cm4.Dst != nil { | ||||
| 		return cm4.Dst | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // correctSource takes oob data and returns new oob data with the Src equal to the Dst | ||||
| func correctSource(oob []byte) []byte { | ||||
| 	dst := parseDstFromOOB(oob) | ||||
| 	if dst == nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 	// 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 | ||||
| } | ||||
							
								
								
									
										35
									
								
								vendor/github.com/miekg/dns/udp_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								vendor/github.com/miekg/dns/udp_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| // +build windows | ||||
| 
 | ||||
| package dns | ||||
| 
 | ||||
| import "net" | ||||
| 
 | ||||
| // SessionUDP holds the remote address | ||||
| type SessionUDP struct { | ||||
| 	raddr *net.UDPAddr | ||||
| } | ||||
| 
 | ||||
| // RemoteAddr returns the remote network address. | ||||
| 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 { | ||||
| 		return n, nil, err | ||||
| 	} | ||||
| 	return n, &SessionUDP{raddr.(*net.UDPAddr)}, err | ||||
| } | ||||
| 
 | ||||
| // 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) { | ||||
| 	return conn.WriteTo(b, session.raddr) | ||||
| } | ||||
| 
 | ||||
| // 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 } | ||||
							
								
								
									
										112
									
								
								vendor/github.com/miekg/dns/update.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								vendor/github.com/miekg/dns/update.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | |||
| package dns | ||||
| 
 | ||||
| // NameUsed sets the RRs in the prereq section to | ||||
| // "Name is in use" RRs. RFC 2136 section 2.4.4. | ||||
| func (u *Msg) NameUsed(rr []RR) { | ||||
| 	if u.Answer == nil { | ||||
| 		u.Answer = make([]RR, 0, len(rr)) | ||||
| 	} | ||||
| 	for _, r := range rr { | ||||
| 		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // NameNotUsed sets the RRs in the prereq section to | ||||
| // "Name is in not use" RRs. RFC 2136 section 2.4.5. | ||||
| func (u *Msg) NameNotUsed(rr []RR) { | ||||
| 	if u.Answer == nil { | ||||
| 		u.Answer = make([]RR, 0, len(rr)) | ||||
| 	} | ||||
| 	for _, r := range rr { | ||||
| 		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassNONE}}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Used sets the RRs in the prereq section to | ||||
| // "RRset exists (value dependent -- with rdata)" RRs. RFC 2136 section 2.4.2. | ||||
| func (u *Msg) Used(rr []RR) { | ||||
| 	if len(u.Question) == 0 { | ||||
| 		panic("dns: empty question section") | ||||
| 	} | ||||
| 	if u.Answer == nil { | ||||
| 		u.Answer = make([]RR, 0, len(rr)) | ||||
| 	} | ||||
| 	for _, r := range rr { | ||||
| 		hdr := r.Header() | ||||
| 		hdr.Class = u.Question[0].Qclass | ||||
| 		hdr.Ttl = 0 | ||||
| 		u.Answer = append(u.Answer, r) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // RRsetUsed sets the RRs in the prereq section to | ||||
| // "RRset exists (value independent -- no rdata)" RRs. RFC 2136 section 2.4.1. | ||||
| func (u *Msg) RRsetUsed(rr []RR) { | ||||
| 	if u.Answer == nil { | ||||
| 		u.Answer = make([]RR, 0, len(rr)) | ||||
| 	} | ||||
| 	for _, r := range rr { | ||||
| 		h := r.Header() | ||||
| 		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // RRsetNotUsed sets the RRs in the prereq section to | ||||
| // "RRset does not exist" RRs. RFC 2136 section 2.4.3. | ||||
| func (u *Msg) RRsetNotUsed(rr []RR) { | ||||
| 	if u.Answer == nil { | ||||
| 		u.Answer = make([]RR, 0, len(rr)) | ||||
| 	} | ||||
| 	for _, r := range rr { | ||||
| 		h := r.Header() | ||||
| 		u.Answer = append(u.Answer, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassNONE}}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Insert creates a dynamic update packet that adds an complete RRset, see RFC 2136 section 2.5.1. | ||||
| func (u *Msg) Insert(rr []RR) { | ||||
| 	if len(u.Question) == 0 { | ||||
| 		panic("dns: empty question section") | ||||
| 	} | ||||
| 	if u.Ns == nil { | ||||
| 		u.Ns = make([]RR, 0, len(rr)) | ||||
| 	} | ||||
| 	for _, r := range rr { | ||||
| 		r.Header().Class = u.Question[0].Qclass | ||||
| 		u.Ns = append(u.Ns, r) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // RemoveRRset creates a dynamic update packet that deletes an RRset, see RFC 2136 section 2.5.2. | ||||
| func (u *Msg) RemoveRRset(rr []RR) { | ||||
| 	if u.Ns == nil { | ||||
| 		u.Ns = make([]RR, 0, len(rr)) | ||||
| 	} | ||||
| 	for _, r := range rr { | ||||
| 		h := r.Header() | ||||
| 		u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: h.Name, Ttl: 0, Rrtype: h.Rrtype, Class: ClassANY}}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // RemoveName creates a dynamic update packet that deletes all RRsets of a name, see RFC 2136 section 2.5.3 | ||||
| func (u *Msg) RemoveName(rr []RR) { | ||||
| 	if u.Ns == nil { | ||||
| 		u.Ns = make([]RR, 0, len(rr)) | ||||
| 	} | ||||
| 	for _, r := range rr { | ||||
| 		u.Ns = append(u.Ns, &ANY{Hdr: RR_Header{Name: r.Header().Name, Ttl: 0, Rrtype: TypeANY, Class: ClassANY}}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Remove creates a dynamic update packet deletes RR from a RRSset, see RFC 2136 section 2.5.4 | ||||
| func (u *Msg) Remove(rr []RR) { | ||||
| 	if u.Ns == nil { | ||||
| 		u.Ns = make([]RR, 0, len(rr)) | ||||
| 	} | ||||
| 	for _, r := range rr { | ||||
| 		h := r.Header() | ||||
| 		h.Class = ClassNONE | ||||
| 		h.Ttl = 0 | ||||
| 		u.Ns = append(u.Ns, r) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/github.com/miekg/dns/version.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/miekg/dns/version.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| package dns | ||||
| 
 | ||||
| import "fmt" | ||||
| 
 | ||||
| // Version is current version of this library. | ||||
| var Version = v{1, 1, 49} | ||||
| 
 | ||||
| // 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) | ||||
| } | ||||
							
								
								
									
										271
									
								
								vendor/github.com/miekg/dns/xfr.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										271
									
								
								vendor/github.com/miekg/dns/xfr.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,271 @@ | |||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // Envelope is used when doing a zone transfer with a remote server. | ||||
| type Envelope struct { | ||||
| 	RR    []RR  // The set of RRs in the answer section of the xfr reply message. | ||||
| 	Error error // If something went wrong, this contains the error. | ||||
| } | ||||
| 
 | ||||
| // A Transfer defines parameters that are used during a zone transfer. | ||||
| type Transfer struct { | ||||
| 	*Conn | ||||
| 	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 | ||||
| 	TsigProvider   TsigProvider      // An implementation of the TsigProvider interface. If defined it replaces TsigSecret and is used for all TSIG operations. | ||||
| 	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 | ||||
| } | ||||
| 
 | ||||
| func (t *Transfer) tsigProvider() TsigProvider { | ||||
| 	if t.TsigProvider != nil { | ||||
| 		return t.TsigProvider | ||||
| 	} | ||||
| 	if t.TsigSecret != nil { | ||||
| 		return tsigSecretProvider(t.TsigSecret) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // TODO: Think we need to away to stop the transfer | ||||
| 
 | ||||
| // In performs an incoming transfer with the server in a. | ||||
| // If you would like to set the source IP, or some other attribute | ||||
| // of a Dialer for a Transfer, you can do so by specifying the attributes | ||||
| // in the Transfer.Conn: | ||||
| // | ||||
| //	d := net.Dialer{LocalAddr: transfer_source} | ||||
| //	con, err := d.Dial("tcp", master) | ||||
| //	dnscon := &dns.Conn{Conn:con} | ||||
| //	transfer = &dns.Transfer{Conn: dnscon} | ||||
| //	channel, err := transfer.In(message, master) | ||||
| // | ||||
| func (t *Transfer) In(q *Msg, a string) (env chan *Envelope, err error) { | ||||
| 	switch q.Question[0].Qtype { | ||||
| 	case TypeAXFR, TypeIXFR: | ||||
| 	default: | ||||
| 		return nil, &Error{"unsupported question type"} | ||||
| 	} | ||||
| 
 | ||||
| 	timeout := dnsTimeout | ||||
| 	if t.DialTimeout != 0 { | ||||
| 		timeout = t.DialTimeout | ||||
| 	} | ||||
| 
 | ||||
| 	if t.Conn == nil { | ||||
| 		t.Conn, err = DialTimeout("tcp", a, timeout) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if err := t.WriteMsg(q); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	env = make(chan *Envelope) | ||||
| 	switch q.Question[0].Qtype { | ||||
| 	case TypeAXFR: | ||||
| 		go t.inAxfr(q, env) | ||||
| 	case TypeIXFR: | ||||
| 		go t.inIxfr(q, env) | ||||
| 	} | ||||
| 
 | ||||
| 	return env, nil | ||||
| } | ||||
| 
 | ||||
| func (t *Transfer) inAxfr(q *Msg, c chan *Envelope) { | ||||
| 	first := true | ||||
| 	defer t.Close() | ||||
| 	defer close(c) | ||||
| 	timeout := dnsTimeout | ||||
| 	if t.ReadTimeout != 0 { | ||||
| 		timeout = t.ReadTimeout | ||||
| 	} | ||||
| 	for { | ||||
| 		t.Conn.SetReadDeadline(time.Now().Add(timeout)) | ||||
| 		in, err := t.ReadMsg() | ||||
| 		if err != nil { | ||||
| 			c <- &Envelope{nil, err} | ||||
| 			return | ||||
| 		} | ||||
| 		if q.Id != in.Id { | ||||
| 			c <- &Envelope{in.Answer, ErrId} | ||||
| 			return | ||||
| 		} | ||||
| 		if first { | ||||
| 			if in.Rcode != RcodeSuccess { | ||||
| 				c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}} | ||||
| 				return | ||||
| 			} | ||||
| 			if !isSOAFirst(in) { | ||||
| 				c <- &Envelope{in.Answer, ErrSoa} | ||||
| 				return | ||||
| 			} | ||||
| 			first = !first | ||||
| 			// only one answer that is SOA, receive more | ||||
| 			if len(in.Answer) == 1 { | ||||
| 				t.tsigTimersOnly = true | ||||
| 				c <- &Envelope{in.Answer, nil} | ||||
| 				continue | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if !first { | ||||
| 			t.tsigTimersOnly = true // Subsequent envelopes use this. | ||||
| 			if isSOALast(in) { | ||||
| 				c <- &Envelope{in.Answer, nil} | ||||
| 				return | ||||
| 			} | ||||
| 			c <- &Envelope{in.Answer, nil} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *Transfer) inIxfr(q *Msg, c chan *Envelope) { | ||||
| 	var serial uint32 // The first serial seen is the current server serial | ||||
| 	axfr := true | ||||
| 	n := 0 | ||||
| 	qser := q.Ns[0].(*SOA).Serial | ||||
| 	defer t.Close() | ||||
| 	defer close(c) | ||||
| 	timeout := dnsTimeout | ||||
| 	if t.ReadTimeout != 0 { | ||||
| 		timeout = t.ReadTimeout | ||||
| 	} | ||||
| 	for { | ||||
| 		t.SetReadDeadline(time.Now().Add(timeout)) | ||||
| 		in, err := t.ReadMsg() | ||||
| 		if err != nil { | ||||
| 			c <- &Envelope{nil, err} | ||||
| 			return | ||||
| 		} | ||||
| 		if q.Id != in.Id { | ||||
| 			c <- &Envelope{in.Answer, ErrId} | ||||
| 			return | ||||
| 		} | ||||
| 		if in.Rcode != RcodeSuccess { | ||||
| 			c <- &Envelope{in.Answer, &Error{err: fmt.Sprintf(errXFR, in.Rcode)}} | ||||
| 			return | ||||
| 		} | ||||
| 		if n == 0 { | ||||
| 			// Check if the returned answer is ok | ||||
| 			if !isSOAFirst(in) { | ||||
| 				c <- &Envelope{in.Answer, ErrSoa} | ||||
| 				return | ||||
| 			} | ||||
| 			// This serial is important | ||||
| 			serial = in.Answer[0].(*SOA).Serial | ||||
| 			// Check if there are no changes in zone | ||||
| 			if qser >= serial { | ||||
| 				c <- &Envelope{in.Answer, nil} | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 		// Now we need to check each message for SOA records, to see what we need to do | ||||
| 		t.tsigTimersOnly = true | ||||
| 		for _, rr := range in.Answer { | ||||
| 			if v, ok := rr.(*SOA); ok { | ||||
| 				if v.Serial == serial { | ||||
| 					n++ | ||||
| 					// quit if it's a full axfr or the the servers' SOA is repeated the third time | ||||
| 					if axfr && n == 2 || n == 3 { | ||||
| 						c <- &Envelope{in.Answer, nil} | ||||
| 						return | ||||
| 					} | ||||
| 				} else if axfr { | ||||
| 					// it's an ixfr | ||||
| 					axfr = false | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		c <- &Envelope{in.Answer, nil} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Out performs an outgoing transfer with the client connecting in w. | ||||
| // Basic use pattern: | ||||
| // | ||||
| //	ch := make(chan *dns.Envelope) | ||||
| //	tr := new(dns.Transfer) | ||||
| //	var wg sync.WaitGroup | ||||
| //	go func() { | ||||
| //		tr.Out(w, r, ch) | ||||
| //		wg.Done() | ||||
| //	}() | ||||
| //	ch <- &dns.Envelope{RR: []dns.RR{soa, rr1, rr2, rr3, soa}} | ||||
| //	close(ch) | ||||
| //	wg.Wait() // wait until everything is written out | ||||
| //	w.Close() // close connection | ||||
| // | ||||
| // The server is responsible for sending the correct sequence of RRs through the channel ch. | ||||
| func (t *Transfer) Out(w ResponseWriter, q *Msg, ch chan *Envelope) error { | ||||
| 	for x := range ch { | ||||
| 		r := new(Msg) | ||||
| 		// Compress? | ||||
| 		r.SetReply(q) | ||||
| 		r.Authoritative = true | ||||
| 		// assume it fits TODO(miek): fix | ||||
| 		r.Answer = append(r.Answer, x.RR...) | ||||
| 		if tsig := q.IsTsig(); tsig != nil && w.TsigStatus() == nil { | ||||
| 			r.SetTsig(tsig.Hdr.Name, tsig.Algorithm, tsig.Fudge, time.Now().Unix()) | ||||
| 		} | ||||
| 		if err := w.WriteMsg(r); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		w.TsigTimersOnly(true) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // ReadMsg reads a message from the transfer connection t. | ||||
| func (t *Transfer) ReadMsg() (*Msg, error) { | ||||
| 	m := new(Msg) | ||||
| 	p := make([]byte, MaxMsgSize) | ||||
| 	n, err := t.Read(p) | ||||
| 	if err != nil && n == 0 { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	p = p[:n] | ||||
| 	if err := m.Unpack(p); err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if ts, tp := m.IsTsig(), t.tsigProvider(); ts != nil && tp != nil { | ||||
| 		// Need to work on the original message p, as that was used to calculate the tsig. | ||||
| 		err = tsigVerifyProvider(p, tp, t.tsigRequestMAC, t.tsigTimersOnly) | ||||
| 		t.tsigRequestMAC = ts.MAC | ||||
| 	} | ||||
| 	return m, err | ||||
| } | ||||
| 
 | ||||
| // WriteMsg writes a message through the transfer connection t. | ||||
| func (t *Transfer) WriteMsg(m *Msg) (err error) { | ||||
| 	var out []byte | ||||
| 	if ts, tp := m.IsTsig(), t.tsigProvider(); ts != nil && tp != nil { | ||||
| 		out, t.tsigRequestMAC, err = tsigGenerateProvider(m, tp, t.tsigRequestMAC, t.tsigTimersOnly) | ||||
| 	} else { | ||||
| 		out, err = m.Pack() | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	_, err = t.Write(out) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| func isSOAFirst(in *Msg) bool { | ||||
| 	return len(in.Answer) > 0 && | ||||
| 		in.Answer[0].Header().Rrtype == TypeSOA | ||||
| } | ||||
| 
 | ||||
| func isSOALast(in *Msg) bool { | ||||
| 	return len(in.Answer) > 0 && | ||||
| 		in.Answer[len(in.Answer)-1].Header().Rrtype == TypeSOA | ||||
| } | ||||
| 
 | ||||
| const errXFR = "bad xfr rcode: %d" | ||||
							
								
								
									
										1340
									
								
								vendor/github.com/miekg/dns/zduplicate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1340
									
								
								vendor/github.com/miekg/dns/zduplicate.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										2875
									
								
								vendor/github.com/miekg/dns/zmsg.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2875
									
								
								vendor/github.com/miekg/dns/zmsg.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										952
									
								
								vendor/github.com/miekg/dns/ztypes.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										952
									
								
								vendor/github.com/miekg/dns/ztypes.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,952 @@ | |||
| // Code generated by "go run types_generate.go"; DO NOT EDIT. | ||||
| 
 | ||||
| package dns | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/base64" | ||||
| 	"net" | ||||
| ) | ||||
| 
 | ||||
| // TypeToRR is a map of constructors for each RR type. | ||||
| var TypeToRR = map[uint16]func() RR{ | ||||
| 	TypeA:          func() RR { return new(A) }, | ||||
| 	TypeAAAA:       func() RR { return new(AAAA) }, | ||||
| 	TypeAFSDB:      func() RR { return new(AFSDB) }, | ||||
| 	TypeANY:        func() RR { return new(ANY) }, | ||||
| 	TypeAPL:        func() RR { return new(APL) }, | ||||
| 	TypeAVC:        func() RR { return new(AVC) }, | ||||
| 	TypeCAA:        func() RR { return new(CAA) }, | ||||
| 	TypeCDNSKEY:    func() RR { return new(CDNSKEY) }, | ||||
| 	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) }, | ||||
| 	TypeDNSKEY:     func() RR { return new(DNSKEY) }, | ||||
| 	TypeDS:         func() RR { return new(DS) }, | ||||
| 	TypeEID:        func() RR { return new(EID) }, | ||||
| 	TypeEUI48:      func() RR { return new(EUI48) }, | ||||
| 	TypeEUI64:      func() RR { return new(EUI64) }, | ||||
| 	TypeGID:        func() RR { return new(GID) }, | ||||
| 	TypeGPOS:       func() RR { return new(GPOS) }, | ||||
| 	TypeHINFO:      func() RR { return new(HINFO) }, | ||||
| 	TypeHIP:        func() RR { return new(HIP) }, | ||||
| 	TypeHTTPS:      func() RR { return new(HTTPS) }, | ||||
| 	TypeKEY:        func() RR { return new(KEY) }, | ||||
| 	TypeKX:         func() RR { return new(KX) }, | ||||
| 	TypeL32:        func() RR { return new(L32) }, | ||||
| 	TypeL64:        func() RR { return new(L64) }, | ||||
| 	TypeLOC:        func() RR { return new(LOC) }, | ||||
| 	TypeLP:         func() RR { return new(LP) }, | ||||
| 	TypeMB:         func() RR { return new(MB) }, | ||||
| 	TypeMD:         func() RR { return new(MD) }, | ||||
| 	TypeMF:         func() RR { return new(MF) }, | ||||
| 	TypeMG:         func() RR { return new(MG) }, | ||||
| 	TypeMINFO:      func() RR { return new(MINFO) }, | ||||
| 	TypeMR:         func() RR { return new(MR) }, | ||||
| 	TypeMX:         func() RR { return new(MX) }, | ||||
| 	TypeNAPTR:      func() RR { return new(NAPTR) }, | ||||
| 	TypeNID:        func() RR { return new(NID) }, | ||||
| 	TypeNIMLOC:     func() RR { return new(NIMLOC) }, | ||||
| 	TypeNINFO:      func() RR { return new(NINFO) }, | ||||
| 	TypeNS:         func() RR { return new(NS) }, | ||||
| 	TypeNSAPPTR:    func() RR { return new(NSAPPTR) }, | ||||
| 	TypeNSEC:       func() RR { return new(NSEC) }, | ||||
| 	TypeNSEC3:      func() RR { return new(NSEC3) }, | ||||
| 	TypeNSEC3PARAM: func() RR { return new(NSEC3PARAM) }, | ||||
| 	TypeNULL:       func() RR { return new(NULL) }, | ||||
| 	TypeOPENPGPKEY: func() RR { return new(OPENPGPKEY) }, | ||||
| 	TypeOPT:        func() RR { return new(OPT) }, | ||||
| 	TypePTR:        func() RR { return new(PTR) }, | ||||
| 	TypePX:         func() RR { return new(PX) }, | ||||
| 	TypeRKEY:       func() RR { return new(RKEY) }, | ||||
| 	TypeRP:         func() RR { return new(RP) }, | ||||
| 	TypeRRSIG:      func() RR { return new(RRSIG) }, | ||||
| 	TypeRT:         func() RR { return new(RT) }, | ||||
| 	TypeSIG:        func() RR { return new(SIG) }, | ||||
| 	TypeSMIMEA:     func() RR { return new(SMIMEA) }, | ||||
| 	TypeSOA:        func() RR { return new(SOA) }, | ||||
| 	TypeSPF:        func() RR { return new(SPF) }, | ||||
| 	TypeSRV:        func() RR { return new(SRV) }, | ||||
| 	TypeSSHFP:      func() RR { return new(SSHFP) }, | ||||
| 	TypeSVCB:       func() RR { return new(SVCB) }, | ||||
| 	TypeTA:         func() RR { return new(TA) }, | ||||
| 	TypeTALINK:     func() RR { return new(TALINK) }, | ||||
| 	TypeTKEY:       func() RR { return new(TKEY) }, | ||||
| 	TypeTLSA:       func() RR { return new(TLSA) }, | ||||
| 	TypeTSIG:       func() RR { return new(TSIG) }, | ||||
| 	TypeTXT:        func() RR { return new(TXT) }, | ||||
| 	TypeUID:        func() RR { return new(UID) }, | ||||
| 	TypeUINFO:      func() RR { return new(UINFO) }, | ||||
| 	TypeURI:        func() RR { return new(URI) }, | ||||
| 	TypeX25:        func() RR { return new(X25) }, | ||||
| 	TypeZONEMD:     func() RR { return new(ZONEMD) }, | ||||
| } | ||||
| 
 | ||||
| // TypeToString is a map of strings for each RR type. | ||||
| var TypeToString = map[uint16]string{ | ||||
| 	TypeA:          "A", | ||||
| 	TypeAAAA:       "AAAA", | ||||
| 	TypeAFSDB:      "AFSDB", | ||||
| 	TypeANY:        "ANY", | ||||
| 	TypeAPL:        "APL", | ||||
| 	TypeATMA:       "ATMA", | ||||
| 	TypeAVC:        "AVC", | ||||
| 	TypeAXFR:       "AXFR", | ||||
| 	TypeCAA:        "CAA", | ||||
| 	TypeCDNSKEY:    "CDNSKEY", | ||||
| 	TypeCDS:        "CDS", | ||||
| 	TypeCERT:       "CERT", | ||||
| 	TypeCNAME:      "CNAME", | ||||
| 	TypeCSYNC:      "CSYNC", | ||||
| 	TypeDHCID:      "DHCID", | ||||
| 	TypeDLV:        "DLV", | ||||
| 	TypeDNAME:      "DNAME", | ||||
| 	TypeDNSKEY:     "DNSKEY", | ||||
| 	TypeDS:         "DS", | ||||
| 	TypeEID:        "EID", | ||||
| 	TypeEUI48:      "EUI48", | ||||
| 	TypeEUI64:      "EUI64", | ||||
| 	TypeGID:        "GID", | ||||
| 	TypeGPOS:       "GPOS", | ||||
| 	TypeHINFO:      "HINFO", | ||||
| 	TypeHIP:        "HIP", | ||||
| 	TypeHTTPS:      "HTTPS", | ||||
| 	TypeISDN:       "ISDN", | ||||
| 	TypeIXFR:       "IXFR", | ||||
| 	TypeKEY:        "KEY", | ||||
| 	TypeKX:         "KX", | ||||
| 	TypeL32:        "L32", | ||||
| 	TypeL64:        "L64", | ||||
| 	TypeLOC:        "LOC", | ||||
| 	TypeLP:         "LP", | ||||
| 	TypeMAILA:      "MAILA", | ||||
| 	TypeMAILB:      "MAILB", | ||||
| 	TypeMB:         "MB", | ||||
| 	TypeMD:         "MD", | ||||
| 	TypeMF:         "MF", | ||||
| 	TypeMG:         "MG", | ||||
| 	TypeMINFO:      "MINFO", | ||||
| 	TypeMR:         "MR", | ||||
| 	TypeMX:         "MX", | ||||
| 	TypeNAPTR:      "NAPTR", | ||||
| 	TypeNID:        "NID", | ||||
| 	TypeNIMLOC:     "NIMLOC", | ||||
| 	TypeNINFO:      "NINFO", | ||||
| 	TypeNS:         "NS", | ||||
| 	TypeNSEC:       "NSEC", | ||||
| 	TypeNSEC3:      "NSEC3", | ||||
| 	TypeNSEC3PARAM: "NSEC3PARAM", | ||||
| 	TypeNULL:       "NULL", | ||||
| 	TypeNXT:        "NXT", | ||||
| 	TypeNone:       "None", | ||||
| 	TypeOPENPGPKEY: "OPENPGPKEY", | ||||
| 	TypeOPT:        "OPT", | ||||
| 	TypePTR:        "PTR", | ||||
| 	TypePX:         "PX", | ||||
| 	TypeRKEY:       "RKEY", | ||||
| 	TypeRP:         "RP", | ||||
| 	TypeRRSIG:      "RRSIG", | ||||
| 	TypeRT:         "RT", | ||||
| 	TypeReserved:   "Reserved", | ||||
| 	TypeSIG:        "SIG", | ||||
| 	TypeSMIMEA:     "SMIMEA", | ||||
| 	TypeSOA:        "SOA", | ||||
| 	TypeSPF:        "SPF", | ||||
| 	TypeSRV:        "SRV", | ||||
| 	TypeSSHFP:      "SSHFP", | ||||
| 	TypeSVCB:       "SVCB", | ||||
| 	TypeTA:         "TA", | ||||
| 	TypeTALINK:     "TALINK", | ||||
| 	TypeTKEY:       "TKEY", | ||||
| 	TypeTLSA:       "TLSA", | ||||
| 	TypeTSIG:       "TSIG", | ||||
| 	TypeTXT:        "TXT", | ||||
| 	TypeUID:        "UID", | ||||
| 	TypeUINFO:      "UINFO", | ||||
| 	TypeUNSPEC:     "UNSPEC", | ||||
| 	TypeURI:        "URI", | ||||
| 	TypeX25:        "X25", | ||||
| 	TypeZONEMD:     "ZONEMD", | ||||
| 	TypeNSAPPTR:    "NSAP-PTR", | ||||
| } | ||||
| 
 | ||||
| func (rr *A) Header() *RR_Header          { return &rr.Hdr } | ||||
| func (rr *AAAA) Header() *RR_Header       { return &rr.Hdr } | ||||
| func (rr *AFSDB) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *ANY) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *APL) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *AVC) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *CAA) Header() *RR_Header        { return &rr.Hdr } | ||||
| 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 } | ||||
| func (rr *DNSKEY) Header() *RR_Header     { return &rr.Hdr } | ||||
| func (rr *DS) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *EID) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *EUI48) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *EUI64) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *GID) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *GPOS) Header() *RR_Header       { return &rr.Hdr } | ||||
| func (rr *HINFO) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *HIP) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *HTTPS) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *KEY) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *KX) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *L32) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *L64) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *LOC) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *LP) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *MB) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *MD) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *MF) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *MG) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *MINFO) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *MR) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *MX) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *NAPTR) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *NID) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *NIMLOC) Header() *RR_Header     { return &rr.Hdr } | ||||
| func (rr *NINFO) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *NS) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *NSAPPTR) Header() *RR_Header    { return &rr.Hdr } | ||||
| func (rr *NSEC) Header() *RR_Header       { return &rr.Hdr } | ||||
| func (rr *NSEC3) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *NSEC3PARAM) Header() *RR_Header { return &rr.Hdr } | ||||
| func (rr *NULL) Header() *RR_Header       { return &rr.Hdr } | ||||
| func (rr *OPENPGPKEY) Header() *RR_Header { return &rr.Hdr } | ||||
| func (rr *OPT) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *PTR) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *PX) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *RFC3597) Header() *RR_Header    { return &rr.Hdr } | ||||
| func (rr *RKEY) Header() *RR_Header       { return &rr.Hdr } | ||||
| func (rr *RP) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *RRSIG) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *RT) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *SIG) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *SMIMEA) Header() *RR_Header     { return &rr.Hdr } | ||||
| func (rr *SOA) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *SPF) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *SRV) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *SSHFP) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *SVCB) Header() *RR_Header       { return &rr.Hdr } | ||||
| func (rr *TA) Header() *RR_Header         { return &rr.Hdr } | ||||
| func (rr *TALINK) Header() *RR_Header     { return &rr.Hdr } | ||||
| func (rr *TKEY) Header() *RR_Header       { return &rr.Hdr } | ||||
| func (rr *TLSA) Header() *RR_Header       { return &rr.Hdr } | ||||
| func (rr *TSIG) Header() *RR_Header       { return &rr.Hdr } | ||||
| func (rr *TXT) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *UID) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *UINFO) Header() *RR_Header      { return &rr.Hdr } | ||||
| func (rr *URI) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *X25) Header() *RR_Header        { return &rr.Hdr } | ||||
| func (rr *ZONEMD) Header() *RR_Header     { return &rr.Hdr } | ||||
| 
 | ||||
| // len() functions | ||||
| func (rr *A) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	if len(rr.A) != 0 { | ||||
| 		l += net.IPv4len | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *AAAA) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	if len(rr.AAAA) != 0 { | ||||
| 		l += net.IPv6len | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *AFSDB) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Subtype | ||||
| 	l += domainNameLen(rr.Hostname, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *ANY) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	return l | ||||
| } | ||||
| func (rr *APL) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	for _, x := range rr.Prefixes { | ||||
| 		l += x.len() | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *AVC) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	for _, x := range rr.Txt { | ||||
| 		l += len(x) + 1 | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *CAA) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l++ // Flag | ||||
| 	l += len(rr.Tag) + 1 | ||||
| 	l += len(rr.Value) | ||||
| 	return l | ||||
| } | ||||
| func (rr *CERT) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Type | ||||
| 	l += 2 // KeyTag | ||||
| 	l++    // Algorithm | ||||
| 	l += base64.StdEncoding.DecodedLen(len(rr.Certificate)) | ||||
| 	return l | ||||
| } | ||||
| func (rr *CNAME) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Target, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *DHCID) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += base64.StdEncoding.DecodedLen(len(rr.Digest)) | ||||
| 	return l | ||||
| } | ||||
| func (rr *DNAME) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Target, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *DNSKEY) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Flags | ||||
| 	l++    // Protocol | ||||
| 	l++    // Algorithm | ||||
| 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) | ||||
| 	return l | ||||
| } | ||||
| func (rr *DS) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // KeyTag | ||||
| 	l++    // Algorithm | ||||
| 	l++    // DigestType | ||||
| 	l += len(rr.Digest) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *EID) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += len(rr.Endpoint) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *EUI48) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 6 // Address | ||||
| 	return l | ||||
| } | ||||
| func (rr *EUI64) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 8 // Address | ||||
| 	return l | ||||
| } | ||||
| func (rr *GID) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 4 // Gid | ||||
| 	return l | ||||
| } | ||||
| func (rr *GPOS) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += len(rr.Longitude) + 1 | ||||
| 	l += len(rr.Latitude) + 1 | ||||
| 	l += len(rr.Altitude) + 1 | ||||
| 	return l | ||||
| } | ||||
| func (rr *HINFO) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += len(rr.Cpu) + 1 | ||||
| 	l += len(rr.Os) + 1 | ||||
| 	return l | ||||
| } | ||||
| func (rr *HIP) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l++    // HitLength | ||||
| 	l++    // PublicKeyAlgorithm | ||||
| 	l += 2 // PublicKeyLength | ||||
| 	l += len(rr.Hit) / 2 | ||||
| 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) | ||||
| 	for _, x := range rr.RendezvousServers { | ||||
| 		l += domainNameLen(x, off+l, compression, false) | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *KX) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Preference | ||||
| 	l += domainNameLen(rr.Exchanger, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *L32) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Preference | ||||
| 	if len(rr.Locator32) != 0 { | ||||
| 		l += net.IPv4len | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *L64) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Preference | ||||
| 	l += 8 // Locator64 | ||||
| 	return l | ||||
| } | ||||
| func (rr *LOC) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l++    // Version | ||||
| 	l++    // Size | ||||
| 	l++    // HorizPre | ||||
| 	l++    // VertPre | ||||
| 	l += 4 // Latitude | ||||
| 	l += 4 // Longitude | ||||
| 	l += 4 // Altitude | ||||
| 	return l | ||||
| } | ||||
| func (rr *LP) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Preference | ||||
| 	l += domainNameLen(rr.Fqdn, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *MB) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Mb, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *MD) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Md, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *MF) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Mf, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *MG) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Mg, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *MINFO) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Rmail, off+l, compression, true) | ||||
| 	l += domainNameLen(rr.Email, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *MR) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Mr, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *MX) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Preference | ||||
| 	l += domainNameLen(rr.Mx, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *NAPTR) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Order | ||||
| 	l += 2 // Preference | ||||
| 	l += len(rr.Flags) + 1 | ||||
| 	l += len(rr.Service) + 1 | ||||
| 	l += len(rr.Regexp) + 1 | ||||
| 	l += domainNameLen(rr.Replacement, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *NID) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Preference | ||||
| 	l += 8 // NodeID | ||||
| 	return l | ||||
| } | ||||
| func (rr *NIMLOC) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += len(rr.Locator) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *NINFO) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	for _, x := range rr.ZSData { | ||||
| 		l += len(x) + 1 | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *NS) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Ns, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *NSAPPTR) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Ptr, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *NSEC3PARAM) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l++    // Hash | ||||
| 	l++    // Flags | ||||
| 	l += 2 // Iterations | ||||
| 	l++    // SaltLength | ||||
| 	l += len(rr.Salt) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *NULL) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += len(rr.Data) | ||||
| 	return l | ||||
| } | ||||
| func (rr *OPENPGPKEY) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) | ||||
| 	return l | ||||
| } | ||||
| func (rr *PTR) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Ptr, off+l, compression, true) | ||||
| 	return l | ||||
| } | ||||
| func (rr *PX) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Preference | ||||
| 	l += domainNameLen(rr.Map822, off+l, compression, false) | ||||
| 	l += domainNameLen(rr.Mapx400, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *RFC3597) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += len(rr.Rdata) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *RKEY) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Flags | ||||
| 	l++    // Protocol | ||||
| 	l++    // Algorithm | ||||
| 	l += base64.StdEncoding.DecodedLen(len(rr.PublicKey)) | ||||
| 	return l | ||||
| } | ||||
| func (rr *RP) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Mbox, off+l, compression, false) | ||||
| 	l += domainNameLen(rr.Txt, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *RRSIG) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // TypeCovered | ||||
| 	l++    // Algorithm | ||||
| 	l++    // Labels | ||||
| 	l += 4 // OrigTtl | ||||
| 	l += 4 // Expiration | ||||
| 	l += 4 // Inception | ||||
| 	l += 2 // KeyTag | ||||
| 	l += domainNameLen(rr.SignerName, off+l, compression, false) | ||||
| 	l += base64.StdEncoding.DecodedLen(len(rr.Signature)) | ||||
| 	return l | ||||
| } | ||||
| func (rr *RT) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Preference | ||||
| 	l += domainNameLen(rr.Host, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *SMIMEA) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l++ // Usage | ||||
| 	l++ // Selector | ||||
| 	l++ // MatchingType | ||||
| 	l += len(rr.Certificate) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *SOA) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Ns, off+l, compression, true) | ||||
| 	l += domainNameLen(rr.Mbox, off+l, compression, true) | ||||
| 	l += 4 // Serial | ||||
| 	l += 4 // Refresh | ||||
| 	l += 4 // Retry | ||||
| 	l += 4 // Expire | ||||
| 	l += 4 // Minttl | ||||
| 	return l | ||||
| } | ||||
| func (rr *SPF) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	for _, x := range rr.Txt { | ||||
| 		l += len(x) + 1 | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *SRV) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Priority | ||||
| 	l += 2 // Weight | ||||
| 	l += 2 // Port | ||||
| 	l += domainNameLen(rr.Target, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *SSHFP) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l++ // Algorithm | ||||
| 	l++ // Type | ||||
| 	l += len(rr.FingerPrint) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *SVCB) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Priority | ||||
| 	l += domainNameLen(rr.Target, off+l, compression, false) | ||||
| 	for _, x := range rr.Value { | ||||
| 		l += 4 + int(x.len()) | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *TA) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // KeyTag | ||||
| 	l++    // Algorithm | ||||
| 	l++    // DigestType | ||||
| 	l += len(rr.Digest) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *TALINK) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.PreviousName, off+l, compression, false) | ||||
| 	l += domainNameLen(rr.NextName, off+l, compression, false) | ||||
| 	return l | ||||
| } | ||||
| func (rr *TKEY) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Algorithm, off+l, compression, false) | ||||
| 	l += 4 // Inception | ||||
| 	l += 4 // Expiration | ||||
| 	l += 2 // Mode | ||||
| 	l += 2 // Error | ||||
| 	l += 2 // KeySize | ||||
| 	l += len(rr.Key) / 2 | ||||
| 	l += 2 // OtherLen | ||||
| 	l += len(rr.OtherData) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *TLSA) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l++ // Usage | ||||
| 	l++ // Selector | ||||
| 	l++ // MatchingType | ||||
| 	l += len(rr.Certificate) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *TSIG) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += domainNameLen(rr.Algorithm, off+l, compression, false) | ||||
| 	l += 6 // TimeSigned | ||||
| 	l += 2 // Fudge | ||||
| 	l += 2 // MACSize | ||||
| 	l += len(rr.MAC) / 2 | ||||
| 	l += 2 // OrigId | ||||
| 	l += 2 // Error | ||||
| 	l += 2 // OtherLen | ||||
| 	l += len(rr.OtherData) / 2 | ||||
| 	return l | ||||
| } | ||||
| func (rr *TXT) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	for _, x := range rr.Txt { | ||||
| 		l += len(x) + 1 | ||||
| 	} | ||||
| 	return l | ||||
| } | ||||
| func (rr *UID) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 4 // Uid | ||||
| 	return l | ||||
| } | ||||
| func (rr *UINFO) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += len(rr.Uinfo) + 1 | ||||
| 	return l | ||||
| } | ||||
| func (rr *URI) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 2 // Priority | ||||
| 	l += 2 // Weight | ||||
| 	l += len(rr.Target) | ||||
| 	return l | ||||
| } | ||||
| func (rr *X25) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += len(rr.PSDNAddress) + 1 | ||||
| 	return l | ||||
| } | ||||
| func (rr *ZONEMD) len(off int, compression map[string]struct{}) int { | ||||
| 	l := rr.Hdr.len(off, compression) | ||||
| 	l += 4 // Serial | ||||
| 	l++    // Scheme | ||||
| 	l++    // Hash | ||||
| 	l += len(rr.Digest) / 2 | ||||
| 	return l | ||||
| } | ||||
| 
 | ||||
| // copy() functions | ||||
| func (rr *A) copy() RR { | ||||
| 	return &A{rr.Hdr, copyIP(rr.A)} | ||||
| } | ||||
| func (rr *AAAA) copy() RR { | ||||
| 	return &AAAA{rr.Hdr, copyIP(rr.AAAA)} | ||||
| } | ||||
| func (rr *AFSDB) copy() RR { | ||||
| 	return &AFSDB{rr.Hdr, rr.Subtype, rr.Hostname} | ||||
| } | ||||
| func (rr *ANY) copy() RR { | ||||
| 	return &ANY{rr.Hdr} | ||||
| } | ||||
| func (rr *APL) copy() RR { | ||||
| 	Prefixes := make([]APLPrefix, len(rr.Prefixes)) | ||||
| 	for i, e := range rr.Prefixes { | ||||
| 		Prefixes[i] = e.copy() | ||||
| 	} | ||||
| 	return &APL{rr.Hdr, Prefixes} | ||||
| } | ||||
| func (rr *AVC) copy() RR { | ||||
| 	Txt := make([]string, len(rr.Txt)) | ||||
| 	copy(Txt, rr.Txt) | ||||
| 	return &AVC{rr.Hdr, Txt} | ||||
| } | ||||
| func (rr *CAA) copy() RR { | ||||
| 	return &CAA{rr.Hdr, rr.Flag, rr.Tag, rr.Value} | ||||
| } | ||||
| func (rr *CDNSKEY) copy() RR { | ||||
| 	return &CDNSKEY{*rr.DNSKEY.copy().(*DNSKEY)} | ||||
| } | ||||
| func (rr *CDS) copy() RR { | ||||
| 	return &CDS{*rr.DS.copy().(*DS)} | ||||
| } | ||||
| func (rr *CERT) copy() RR { | ||||
| 	return &CERT{rr.Hdr, rr.Type, rr.KeyTag, rr.Algorithm, rr.Certificate} | ||||
| } | ||||
| func (rr *CNAME) copy() RR { | ||||
| 	return &CNAME{rr.Hdr, rr.Target} | ||||
| } | ||||
| func (rr *CSYNC) copy() RR { | ||||
| 	TypeBitMap := make([]uint16, len(rr.TypeBitMap)) | ||||
| 	copy(TypeBitMap, rr.TypeBitMap) | ||||
| 	return &CSYNC{rr.Hdr, rr.Serial, rr.Flags, TypeBitMap} | ||||
| } | ||||
| func (rr *DHCID) copy() RR { | ||||
| 	return &DHCID{rr.Hdr, rr.Digest} | ||||
| } | ||||
| func (rr *DLV) copy() RR { | ||||
| 	return &DLV{*rr.DS.copy().(*DS)} | ||||
| } | ||||
| func (rr *DNAME) copy() RR { | ||||
| 	return &DNAME{rr.Hdr, rr.Target} | ||||
| } | ||||
| func (rr *DNSKEY) copy() RR { | ||||
| 	return &DNSKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey} | ||||
| } | ||||
| func (rr *DS) copy() RR { | ||||
| 	return &DS{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} | ||||
| } | ||||
| func (rr *EID) copy() RR { | ||||
| 	return &EID{rr.Hdr, rr.Endpoint} | ||||
| } | ||||
| func (rr *EUI48) copy() RR { | ||||
| 	return &EUI48{rr.Hdr, rr.Address} | ||||
| } | ||||
| func (rr *EUI64) copy() RR { | ||||
| 	return &EUI64{rr.Hdr, rr.Address} | ||||
| } | ||||
| func (rr *GID) copy() RR { | ||||
| 	return &GID{rr.Hdr, rr.Gid} | ||||
| } | ||||
| func (rr *GPOS) copy() RR { | ||||
| 	return &GPOS{rr.Hdr, rr.Longitude, rr.Latitude, rr.Altitude} | ||||
| } | ||||
| func (rr *HINFO) copy() RR { | ||||
| 	return &HINFO{rr.Hdr, rr.Cpu, rr.Os} | ||||
| } | ||||
| func (rr *HIP) copy() RR { | ||||
| 	RendezvousServers := make([]string, len(rr.RendezvousServers)) | ||||
| 	copy(RendezvousServers, rr.RendezvousServers) | ||||
| 	return &HIP{rr.Hdr, rr.HitLength, rr.PublicKeyAlgorithm, rr.PublicKeyLength, rr.Hit, rr.PublicKey, RendezvousServers} | ||||
| } | ||||
| func (rr *HTTPS) copy() RR { | ||||
| 	return &HTTPS{*rr.SVCB.copy().(*SVCB)} | ||||
| } | ||||
| func (rr *KEY) copy() RR { | ||||
| 	return &KEY{*rr.DNSKEY.copy().(*DNSKEY)} | ||||
| } | ||||
| func (rr *KX) copy() RR { | ||||
| 	return &KX{rr.Hdr, rr.Preference, rr.Exchanger} | ||||
| } | ||||
| func (rr *L32) copy() RR { | ||||
| 	return &L32{rr.Hdr, rr.Preference, copyIP(rr.Locator32)} | ||||
| } | ||||
| func (rr *L64) copy() RR { | ||||
| 	return &L64{rr.Hdr, rr.Preference, rr.Locator64} | ||||
| } | ||||
| func (rr *LOC) copy() RR { | ||||
| 	return &LOC{rr.Hdr, rr.Version, rr.Size, rr.HorizPre, rr.VertPre, rr.Latitude, rr.Longitude, rr.Altitude} | ||||
| } | ||||
| func (rr *LP) copy() RR { | ||||
| 	return &LP{rr.Hdr, rr.Preference, rr.Fqdn} | ||||
| } | ||||
| func (rr *MB) copy() RR { | ||||
| 	return &MB{rr.Hdr, rr.Mb} | ||||
| } | ||||
| func (rr *MD) copy() RR { | ||||
| 	return &MD{rr.Hdr, rr.Md} | ||||
| } | ||||
| func (rr *MF) copy() RR { | ||||
| 	return &MF{rr.Hdr, rr.Mf} | ||||
| } | ||||
| func (rr *MG) copy() RR { | ||||
| 	return &MG{rr.Hdr, rr.Mg} | ||||
| } | ||||
| func (rr *MINFO) copy() RR { | ||||
| 	return &MINFO{rr.Hdr, rr.Rmail, rr.Email} | ||||
| } | ||||
| func (rr *MR) copy() RR { | ||||
| 	return &MR{rr.Hdr, rr.Mr} | ||||
| } | ||||
| func (rr *MX) copy() RR { | ||||
| 	return &MX{rr.Hdr, rr.Preference, rr.Mx} | ||||
| } | ||||
| func (rr *NAPTR) copy() RR { | ||||
| 	return &NAPTR{rr.Hdr, rr.Order, rr.Preference, rr.Flags, rr.Service, rr.Regexp, rr.Replacement} | ||||
| } | ||||
| func (rr *NID) copy() RR { | ||||
| 	return &NID{rr.Hdr, rr.Preference, rr.NodeID} | ||||
| } | ||||
| func (rr *NIMLOC) copy() RR { | ||||
| 	return &NIMLOC{rr.Hdr, rr.Locator} | ||||
| } | ||||
| func (rr *NINFO) copy() RR { | ||||
| 	ZSData := make([]string, len(rr.ZSData)) | ||||
| 	copy(ZSData, rr.ZSData) | ||||
| 	return &NINFO{rr.Hdr, ZSData} | ||||
| } | ||||
| func (rr *NS) copy() RR { | ||||
| 	return &NS{rr.Hdr, rr.Ns} | ||||
| } | ||||
| func (rr *NSAPPTR) copy() RR { | ||||
| 	return &NSAPPTR{rr.Hdr, rr.Ptr} | ||||
| } | ||||
| func (rr *NSEC) copy() RR { | ||||
| 	TypeBitMap := make([]uint16, len(rr.TypeBitMap)) | ||||
| 	copy(TypeBitMap, rr.TypeBitMap) | ||||
| 	return &NSEC{rr.Hdr, rr.NextDomain, TypeBitMap} | ||||
| } | ||||
| func (rr *NSEC3) copy() RR { | ||||
| 	TypeBitMap := make([]uint16, len(rr.TypeBitMap)) | ||||
| 	copy(TypeBitMap, rr.TypeBitMap) | ||||
| 	return &NSEC3{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt, rr.HashLength, rr.NextDomain, TypeBitMap} | ||||
| } | ||||
| func (rr *NSEC3PARAM) copy() RR { | ||||
| 	return &NSEC3PARAM{rr.Hdr, rr.Hash, rr.Flags, rr.Iterations, rr.SaltLength, rr.Salt} | ||||
| } | ||||
| func (rr *NULL) copy() RR { | ||||
| 	return &NULL{rr.Hdr, rr.Data} | ||||
| } | ||||
| func (rr *OPENPGPKEY) copy() RR { | ||||
| 	return &OPENPGPKEY{rr.Hdr, rr.PublicKey} | ||||
| } | ||||
| func (rr *OPT) copy() RR { | ||||
| 	Option := make([]EDNS0, len(rr.Option)) | ||||
| 	for i, e := range rr.Option { | ||||
| 		Option[i] = e.copy() | ||||
| 	} | ||||
| 	return &OPT{rr.Hdr, Option} | ||||
| } | ||||
| func (rr *PTR) copy() RR { | ||||
| 	return &PTR{rr.Hdr, rr.Ptr} | ||||
| } | ||||
| func (rr *PX) copy() RR { | ||||
| 	return &PX{rr.Hdr, rr.Preference, rr.Map822, rr.Mapx400} | ||||
| } | ||||
| func (rr *RFC3597) copy() RR { | ||||
| 	return &RFC3597{rr.Hdr, rr.Rdata} | ||||
| } | ||||
| func (rr *RKEY) copy() RR { | ||||
| 	return &RKEY{rr.Hdr, rr.Flags, rr.Protocol, rr.Algorithm, rr.PublicKey} | ||||
| } | ||||
| func (rr *RP) copy() RR { | ||||
| 	return &RP{rr.Hdr, rr.Mbox, rr.Txt} | ||||
| } | ||||
| func (rr *RRSIG) copy() RR { | ||||
| 	return &RRSIG{rr.Hdr, rr.TypeCovered, rr.Algorithm, rr.Labels, rr.OrigTtl, rr.Expiration, rr.Inception, rr.KeyTag, rr.SignerName, rr.Signature} | ||||
| } | ||||
| func (rr *RT) copy() RR { | ||||
| 	return &RT{rr.Hdr, rr.Preference, rr.Host} | ||||
| } | ||||
| func (rr *SIG) copy() RR { | ||||
| 	return &SIG{*rr.RRSIG.copy().(*RRSIG)} | ||||
| } | ||||
| func (rr *SMIMEA) copy() RR { | ||||
| 	return &SMIMEA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} | ||||
| } | ||||
| func (rr *SOA) copy() RR { | ||||
| 	return &SOA{rr.Hdr, rr.Ns, rr.Mbox, rr.Serial, rr.Refresh, rr.Retry, rr.Expire, rr.Minttl} | ||||
| } | ||||
| func (rr *SPF) copy() RR { | ||||
| 	Txt := make([]string, len(rr.Txt)) | ||||
| 	copy(Txt, rr.Txt) | ||||
| 	return &SPF{rr.Hdr, Txt} | ||||
| } | ||||
| func (rr *SRV) copy() RR { | ||||
| 	return &SRV{rr.Hdr, rr.Priority, rr.Weight, rr.Port, rr.Target} | ||||
| } | ||||
| func (rr *SSHFP) copy() RR { | ||||
| 	return &SSHFP{rr.Hdr, rr.Algorithm, rr.Type, rr.FingerPrint} | ||||
| } | ||||
| func (rr *SVCB) copy() RR { | ||||
| 	Value := make([]SVCBKeyValue, len(rr.Value)) | ||||
| 	for i, e := range rr.Value { | ||||
| 		Value[i] = e.copy() | ||||
| 	} | ||||
| 	return &SVCB{rr.Hdr, rr.Priority, rr.Target, Value} | ||||
| } | ||||
| func (rr *TA) copy() RR { | ||||
| 	return &TA{rr.Hdr, rr.KeyTag, rr.Algorithm, rr.DigestType, rr.Digest} | ||||
| } | ||||
| func (rr *TALINK) copy() RR { | ||||
| 	return &TALINK{rr.Hdr, rr.PreviousName, rr.NextName} | ||||
| } | ||||
| func (rr *TKEY) copy() RR { | ||||
| 	return &TKEY{rr.Hdr, rr.Algorithm, rr.Inception, rr.Expiration, rr.Mode, rr.Error, rr.KeySize, rr.Key, rr.OtherLen, rr.OtherData} | ||||
| } | ||||
| func (rr *TLSA) copy() RR { | ||||
| 	return &TLSA{rr.Hdr, rr.Usage, rr.Selector, rr.MatchingType, rr.Certificate} | ||||
| } | ||||
| func (rr *TSIG) copy() RR { | ||||
| 	return &TSIG{rr.Hdr, rr.Algorithm, rr.TimeSigned, rr.Fudge, rr.MACSize, rr.MAC, rr.OrigId, rr.Error, rr.OtherLen, rr.OtherData} | ||||
| } | ||||
| func (rr *TXT) copy() RR { | ||||
| 	Txt := make([]string, len(rr.Txt)) | ||||
| 	copy(Txt, rr.Txt) | ||||
| 	return &TXT{rr.Hdr, Txt} | ||||
| } | ||||
| func (rr *UID) copy() RR { | ||||
| 	return &UID{rr.Hdr, rr.Uid} | ||||
| } | ||||
| func (rr *UINFO) copy() RR { | ||||
| 	return &UINFO{rr.Hdr, rr.Uinfo} | ||||
| } | ||||
| func (rr *URI) copy() RR { | ||||
| 	return &URI{rr.Hdr, rr.Priority, rr.Weight, rr.Target} | ||||
| } | ||||
| func (rr *X25) copy() RR { | ||||
| 	return &X25{rr.Hdr, rr.PSDNAddress} | ||||
| } | ||||
| func (rr *ZONEMD) copy() RR { | ||||
| 	return &ZONEMD{rr.Hdr, rr.Serial, rr.Scheme, rr.Hash, rr.Digest} | ||||
| } | ||||
							
								
								
									
										41
									
								
								vendor/golang.org/x/net/bpf/asm.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/golang.org/x/net/bpf/asm.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 | ||||
| } | ||||
							
								
								
									
										222
									
								
								vendor/golang.org/x/net/bpf/constants.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										222
									
								
								vendor/golang.org/x/net/bpf/constants.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,222 @@ | |||
| // 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. | ||||
| // K can be RegX for JumpIfX | ||||
| 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 & opClsJump | ||||
| 	opMaskOperand  = 0x08 | ||||
| 	opMaskOperator = 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 | ||||
| ) | ||||
| 
 | ||||
| // Operand for ALU and Jump instructions | ||||
| type opOperand uint16 | ||||
| 
 | ||||
| // Supported operand sources. | ||||
| const ( | ||||
| 	opOperandConstant opOperand = iota << 3 | ||||
| 	opOperandX | ||||
| ) | ||||
| 
 | ||||
| // An jumpOp is a conditional jump condition. | ||||
| type jumpOp uint16 | ||||
| 
 | ||||
| // Supported jump conditions. | ||||
| const ( | ||||
| 	opJumpAlways jumpOp = iota << 4 | ||||
| 	opJumpEqual | ||||
| 	opJumpGT | ||||
| 	opJumpGE | ||||
| 	opJumpSet | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	opRetSrcConstant uint16 = iota << 4 | ||||
| 	opRetSrcA | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	opMiscTAX = 0x00 | ||||
| 	opMiscTXA = 0x80 | ||||
| ) | ||||
							
								
								
									
										80
									
								
								vendor/golang.org/x/net/bpf/doc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								vendor/golang.org/x/net/bpf/doc.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 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" | ||||
							
								
								
									
										726
									
								
								vendor/golang.org/x/net/bpf/instructions.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										726
									
								
								vendor/golang.org/x/net/bpf/instructions.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,726 @@ | |||
| // 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: | ||||
| 			switch operand := opOperand(ri.Op & opMaskOperand); operand { | ||||
| 			case opOperandX: | ||||
| 				return ALUOpX{Op: op} | ||||
| 			case opOperandConstant: | ||||
| 				return ALUOpConstant{Op: op, Val: ri.K} | ||||
| 			default: | ||||
| 				return ri | ||||
| 			} | ||||
| 		case aluOpNeg: | ||||
| 			return NegateA{} | ||||
| 		default: | ||||
| 			return ri | ||||
| 		} | ||||
| 
 | ||||
| 	case opClsJump: | ||||
| 		switch op := jumpOp(ri.Op & opMaskOperator); op { | ||||
| 		case opJumpAlways: | ||||
| 			return Jump{Skip: ri.K} | ||||
| 		case opJumpEqual, opJumpGT, opJumpGE, opJumpSet: | ||||
| 			cond, skipTrue, skipFalse := jumpOpToTest(op, ri.Jt, ri.Jf) | ||||
| 			switch operand := opOperand(ri.Op & opMaskOperand); operand { | ||||
| 			case opOperandX: | ||||
| 				return JumpIfX{Cond: cond, SkipTrue: skipTrue, SkipFalse: skipFalse} | ||||
| 			case opOperandConstant: | ||||
| 				return JumpIf{Cond: cond, Val: ri.K, SkipTrue: skipTrue, SkipFalse: skipFalse} | ||||
| 			default: | ||||
| 				return ri | ||||
| 			} | ||||
| 		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 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func jumpOpToTest(op jumpOp, skipTrue uint8, skipFalse uint8) (JumpTest, uint8, uint8) { | ||||
| 	var test JumpTest | ||||
| 
 | ||||
| 	// Decode "fake" jump conditions that don't appear in machine code | ||||
| 	// Ensures the Assemble -> Disassemble stage recreates the same instructions | ||||
| 	// See https://github.com/golang/go/issues/18470 | ||||
| 	if skipTrue == 0 { | ||||
| 		switch op { | ||||
| 		case opJumpEqual: | ||||
| 			test = JumpNotEqual | ||||
| 		case opJumpGT: | ||||
| 			test = JumpLessOrEqual | ||||
| 		case opJumpGE: | ||||
| 			test = JumpLessThan | ||||
| 		case opJumpSet: | ||||
| 			test = JumpBitsNotSet | ||||
| 		} | ||||
| 
 | ||||
| 		return test, skipFalse, 0 | ||||
| 	} | ||||
| 
 | ||||
| 	switch op { | ||||
| 	case opJumpEqual: | ||||
| 		test = JumpEqual | ||||
| 	case opJumpGT: | ||||
| 		test = JumpGreaterThan | ||||
| 	case opJumpGE: | ||||
| 		test = JumpGreaterOrEqual | ||||
| 	case opJumpSet: | ||||
| 		test = JumpBitsSet | ||||
| 	} | ||||
| 
 | ||||
| 	return test, skipTrue, skipFalse | ||||
| } | ||||
| 
 | ||||
| // 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 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 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 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 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 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 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 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 | uint16(opOperandConstant) | uint16(a.Op), | ||||
| 		K:  a.Val, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // String returns 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 | uint16(opOperandX) | uint16(a.Op), | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // String returns 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 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 | uint16(opJumpAlways), | ||||
| 		K:  a.Skip, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // String returns 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) { | ||||
| 	return jumpToRaw(a.Cond, opOperandConstant, a.Val, a.SkipTrue, a.SkipFalse) | ||||
| } | ||||
| 
 | ||||
| // String returns the instruction in assembler notation. | ||||
| func (a JumpIf) String() string { | ||||
| 	return jumpToString(a.Cond, fmt.Sprintf("#%d", a.Val), a.SkipTrue, a.SkipFalse) | ||||
| } | ||||
| 
 | ||||
| // JumpIfX skips the following Skip instructions in the program if A | ||||
| // <Cond> X is true. | ||||
| type JumpIfX struct { | ||||
| 	Cond      JumpTest | ||||
| 	SkipTrue  uint8 | ||||
| 	SkipFalse uint8 | ||||
| } | ||||
| 
 | ||||
| // Assemble implements the Instruction Assemble method. | ||||
| func (a JumpIfX) Assemble() (RawInstruction, error) { | ||||
| 	return jumpToRaw(a.Cond, opOperandX, 0, a.SkipTrue, a.SkipFalse) | ||||
| } | ||||
| 
 | ||||
| // String returns the instruction in assembler notation. | ||||
| func (a JumpIfX) String() string { | ||||
| 	return jumpToString(a.Cond, "x", a.SkipTrue, a.SkipFalse) | ||||
| } | ||||
| 
 | ||||
| // jumpToRaw assembles a jump instruction into a RawInstruction | ||||
| func jumpToRaw(test JumpTest, operand opOperand, k uint32, skipTrue, skipFalse uint8) (RawInstruction, error) { | ||||
| 	var ( | ||||
| 		cond jumpOp | ||||
| 		flip bool | ||||
| 	) | ||||
| 	switch test { | ||||
| 	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", test) | ||||
| 	} | ||||
| 	jt, jf := skipTrue, skipFalse | ||||
| 	if flip { | ||||
| 		jt, jf = jf, jt | ||||
| 	} | ||||
| 	return RawInstruction{ | ||||
| 		Op: opClsJump | uint16(cond) | uint16(operand), | ||||
| 		Jt: jt, | ||||
| 		Jf: jf, | ||||
| 		K:  k, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| // jumpToString converts a jump instruction to assembler notation | ||||
| func jumpToString(cond JumpTest, operand string, skipTrue, skipFalse uint8) string { | ||||
| 	switch cond { | ||||
| 	// K == A | ||||
| 	case JumpEqual: | ||||
| 		return conditionalJump(operand, skipTrue, skipFalse, "jeq", "jneq") | ||||
| 	// K != A | ||||
| 	case JumpNotEqual: | ||||
| 		return fmt.Sprintf("jneq %s,%d", operand, skipTrue) | ||||
| 	// K > A | ||||
| 	case JumpGreaterThan: | ||||
| 		return conditionalJump(operand, skipTrue, skipFalse, "jgt", "jle") | ||||
| 	// K < A | ||||
| 	case JumpLessThan: | ||||
| 		return fmt.Sprintf("jlt %s,%d", operand, skipTrue) | ||||
| 	// K >= A | ||||
| 	case JumpGreaterOrEqual: | ||||
| 		return conditionalJump(operand, skipTrue, skipFalse, "jge", "jlt") | ||||
| 	// K <= A | ||||
| 	case JumpLessOrEqual: | ||||
| 		return fmt.Sprintf("jle %s,%d", operand, skipTrue) | ||||
| 	// K & A != 0 | ||||
| 	case JumpBitsSet: | ||||
| 		if skipFalse > 0 { | ||||
| 			return fmt.Sprintf("jset %s,%d,%d", operand, skipTrue, skipFalse) | ||||
| 		} | ||||
| 		return fmt.Sprintf("jset %s,%d", operand, skipTrue) | ||||
| 	// K & A == 0, there is no assembler instruction for JumpBitNotSet, use JumpBitSet and invert skips | ||||
| 	case JumpBitsNotSet: | ||||
| 		return jumpToString(JumpBitsSet, operand, skipFalse, skipTrue) | ||||
| 	default: | ||||
| 		return fmt.Sprintf("unknown JumpTest %#v", cond) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func conditionalJump(operand string, skipTrue, skipFalse uint8, positiveJump, negativeJump string) string { | ||||
| 	if skipTrue > 0 { | ||||
| 		if skipFalse > 0 { | ||||
| 			return fmt.Sprintf("%s %s,%d,%d", positiveJump, operand, skipTrue, skipFalse) | ||||
| 		} | ||||
| 		return fmt.Sprintf("%s %s,%d", positiveJump, operand, skipTrue) | ||||
| 	} | ||||
| 	return fmt.Sprintf("%s %s,%d", negativeJump, operand, 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 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 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 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 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 | ||||
| } | ||||
							
								
								
									
										10
									
								
								vendor/golang.org/x/net/bpf/setter.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/golang.org/x/net/bpf/setter.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 | ||||
| } | ||||
							
								
								
									
										150
									
								
								vendor/golang.org/x/net/bpf/vm.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								vendor/golang.org/x/net/bpf/vm.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,150 @@ | |||
| // 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) | ||||
| 			} | ||||
| 		case JumpIfX: | ||||
| 			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 JumpIfX: | ||||
| 			jump := jumpIfX(ins, regA, regX) | ||||
| 			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 | ||||
| } | ||||
							
								
								
									
										182
									
								
								vendor/golang.org/x/net/bpf/vm_instructions.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								vendor/golang.org/x/net/bpf/vm_instructions.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 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, regA uint32) int { | ||||
| 	return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, ins.Val) | ||||
| } | ||||
| 
 | ||||
| func jumpIfX(ins JumpIfX, regA uint32, regX uint32) int { | ||||
| 	return jumpIfCommon(ins.Cond, ins.SkipTrue, ins.SkipFalse, regA, regX) | ||||
| } | ||||
| 
 | ||||
| func jumpIfCommon(cond JumpTest, skipTrue, skipFalse uint8, regA uint32, value uint32) int { | ||||
| 	var ok bool | ||||
| 
 | ||||
| 	switch cond { | ||||
| 	case JumpEqual: | ||||
| 		ok = regA == value | ||||
| 	case JumpNotEqual: | ||||
| 		ok = regA != value | ||||
| 	case JumpGreaterThan: | ||||
| 		ok = regA > value | ||||
| 	case JumpLessThan: | ||||
| 		ok = regA < value | ||||
| 	case JumpGreaterOrEqual: | ||||
| 		ok = regA >= value | ||||
| 	case JumpLessOrEqual: | ||||
| 		ok = regA <= value | ||||
| 	case JumpBitsSet: | ||||
| 		ok = (regA & value) != 0 | ||||
| 	case JumpBitsNotSet: | ||||
| 		ok = (regA & value) == 0 | ||||
| 	} | ||||
| 
 | ||||
| 	if ok { | ||||
| 		return int(skipTrue) | ||||
| 	} | ||||
| 
 | ||||
| 	return int(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) | ||||
| 
 | ||||
| 	// Size of LoadMemShift is always 1 byte | ||||
| 	if !inBounds(len(in), offset, 1) { | ||||
| 		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 | ||||
| } | ||||
							
								
								
									
										223
									
								
								vendor/golang.org/x/net/internal/iana/const.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								vendor/golang.org/x/net/internal/iana/const.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,223 @@ | |||
| // go generate gen.go | ||||
| // Code 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: 2018-05-04 | ||||
| const ( | ||||
| 	DiffServCS0           = 0x00 // 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 | ||||
| 	NotECNTransport       = 0x00 // Not-ECT (Not ECN-Capable Transport) | ||||
| 	ECNTransport1         = 0x01 // ECT(1) (ECN-Capable Transport(1)) | ||||
| 	ECNTransport0         = 0x02 // ECT(0) (ECN-Capable Transport(0)) | ||||
| 	CongestionExperienced = 0x03 // CE (Congestion Experienced) | ||||
| ) | ||||
| 
 | ||||
| // Protocol Numbers, Updated: 2017-10-13 | ||||
| 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 | ||||
| ) | ||||
| 
 | ||||
| // Address Family Numbers, Updated: 2018-04-02 | ||||
| const ( | ||||
| 	AddrFamilyIPv4                          = 1     // IP (IP version 4) | ||||
| 	AddrFamilyIPv6                          = 2     // IP6 (IP version 6) | ||||
| 	AddrFamilyNSAP                          = 3     // NSAP | ||||
| 	AddrFamilyHDLC                          = 4     // HDLC (8-bit multidrop) | ||||
| 	AddrFamilyBBN1822                       = 5     // BBN 1822 | ||||
| 	AddrFamily802                           = 6     // 802 (includes all 802 media plus Ethernet "canonical format") | ||||
| 	AddrFamilyE163                          = 7     // E.163 | ||||
| 	AddrFamilyE164                          = 8     // E.164 (SMDS, Frame Relay, ATM) | ||||
| 	AddrFamilyF69                           = 9     // F.69 (Telex) | ||||
| 	AddrFamilyX121                          = 10    // X.121 (X.25, Frame Relay) | ||||
| 	AddrFamilyIPX                           = 11    // IPX | ||||
| 	AddrFamilyAppletalk                     = 12    // Appletalk | ||||
| 	AddrFamilyDecnetIV                      = 13    // Decnet IV | ||||
| 	AddrFamilyBanyanVines                   = 14    // Banyan Vines | ||||
| 	AddrFamilyE164withSubaddress            = 15    // E.164 with NSAP format subaddress | ||||
| 	AddrFamilyDNS                           = 16    // DNS (Domain Name System) | ||||
| 	AddrFamilyDistinguishedName             = 17    // Distinguished Name | ||||
| 	AddrFamilyASNumber                      = 18    // AS Number | ||||
| 	AddrFamilyXTPoverIPv4                   = 19    // XTP over IP version 4 | ||||
| 	AddrFamilyXTPoverIPv6                   = 20    // XTP over IP version 6 | ||||
| 	AddrFamilyXTPnativemodeXTP              = 21    // XTP native mode XTP | ||||
| 	AddrFamilyFibreChannelWorldWidePortName = 22    // Fibre Channel World-Wide Port Name | ||||
| 	AddrFamilyFibreChannelWorldWideNodeName = 23    // Fibre Channel World-Wide Node Name | ||||
| 	AddrFamilyGWID                          = 24    // GWID | ||||
| 	AddrFamilyL2VPN                         = 25    // AFI for L2VPN information | ||||
| 	AddrFamilyMPLSTPSectionEndpointID       = 26    // MPLS-TP Section Endpoint Identifier | ||||
| 	AddrFamilyMPLSTPLSPEndpointID           = 27    // MPLS-TP LSP Endpoint Identifier | ||||
| 	AddrFamilyMPLSTPPseudowireEndpointID    = 28    // MPLS-TP Pseudowire Endpoint Identifier | ||||
| 	AddrFamilyMTIPv4                        = 29    // MT IP: Multi-Topology IP version 4 | ||||
| 	AddrFamilyMTIPv6                        = 30    // MT IPv6: Multi-Topology IP version 6 | ||||
| 	AddrFamilyEIGRPCommonServiceFamily      = 16384 // EIGRP Common Service Family | ||||
| 	AddrFamilyEIGRPIPv4ServiceFamily        = 16385 // EIGRP IPv4 Service Family | ||||
| 	AddrFamilyEIGRPIPv6ServiceFamily        = 16386 // EIGRP IPv6 Service Family | ||||
| 	AddrFamilyLISPCanonicalAddressFormat    = 16387 // LISP Canonical Address Format (LCAF) | ||||
| 	AddrFamilyBGPLS                         = 16388 // BGP-LS | ||||
| 	AddrFamily48bitMAC                      = 16389 // 48-bit MAC | ||||
| 	AddrFamily64bitMAC                      = 16390 // 64-bit MAC | ||||
| 	AddrFamilyOUI                           = 16391 // OUI | ||||
| 	AddrFamilyMACFinal24bits                = 16392 // MAC/24 | ||||
| 	AddrFamilyMACFinal40bits                = 16393 // MAC/40 | ||||
| 	AddrFamilyIPv6Initial64bits             = 16394 // IPv6/64 | ||||
| 	AddrFamilyRBridgePortID                 = 16395 // RBridge Port ID | ||||
| 	AddrFamilyTRILLNickname                 = 16396 // TRILL Nickname | ||||
| ) | ||||
							
								
								
									
										12
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +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. | ||||
| 
 | ||||
| //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos | ||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos | ||||
| 
 | ||||
| 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) } | ||||
							
								
								
									
										14
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_bsd.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd | ||||
| // +build aix 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) | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_linux_32bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build (arm || mips || mipsle || 386 || ppc) && linux | ||||
| // +build arm mips mipsle 386 ppc | ||||
| // +build linux | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| func (h *cmsghdr) set(l, lvl, typ int) { | ||||
| 	h.Len = uint32(l) | ||||
| 	h.Level = int32(lvl) | ||||
| 	h.Type = int32(typ) | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_linux_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build (arm64 || amd64 || loong64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux | ||||
| // +build arm64 amd64 loong64 ppc64 ppc64le mips64 mips64le riscv64 s390x | ||||
| // +build linux | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| func (h *cmsghdr) set(l, lvl, typ int) { | ||||
| 	h.Len = uint64(l) | ||||
| 	h.Level = int32(lvl) | ||||
| 	h.Type = int32(typ) | ||||
| } | ||||
							
								
								
									
										14
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_solaris_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build amd64 && solaris | ||||
| // +build amd64,solaris | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| func (h *cmsghdr) set(l, lvl, typ int) { | ||||
| 	h.Len = uint32(l) | ||||
| 	h.Level = int32(lvl) | ||||
| 	h.Type = int32(typ) | ||||
| } | ||||
							
								
								
									
										28
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_stub.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos | ||||
| // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| func controlHeaderLen() int { | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| func controlMessageLen(dataLen int) int { | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| func controlMessageSpace(dataLen int) int { | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| type cmsghdr struct{} | ||||
| 
 | ||||
| func (h *cmsghdr) len() int { return 0 } | ||||
| func (h *cmsghdr) lvl() int { return 0 } | ||||
| func (h *cmsghdr) typ() int { return 0 } | ||||
| 
 | ||||
| func (h *cmsghdr) set(l, lvl, typ int) {} | ||||
							
								
								
									
										22
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| // Copyright 2020 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos | ||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| import "golang.org/x/sys/unix" | ||||
| 
 | ||||
| func controlHeaderLen() int { | ||||
| 	return unix.CmsgLen(0) | ||||
| } | ||||
| 
 | ||||
| func controlMessageLen(dataLen int) int { | ||||
| 	return unix.CmsgLen(dataLen) | ||||
| } | ||||
| 
 | ||||
| func controlMessageSpace(dataLen int) int { | ||||
| 	return unix.CmsgSpace(dataLen) | ||||
| } | ||||
							
								
								
									
										11
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/golang.org/x/net/internal/socket/cmsghdr_zos_s390x.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| // Copyright 2020 The Go Authors. 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 *cmsghdr) set(l, lvl, typ int) { | ||||
| 	h.Len = int32(l) | ||||
| 	h.Level = int32(lvl) | ||||
| 	h.Type = int32(typ) | ||||
| } | ||||
							
								
								
									
										26
									
								
								vendor/golang.org/x/net/internal/socket/complete_dontwait.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/golang.org/x/net/internal/socket/complete_dontwait.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| // Copyright 2021 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris | ||||
| // +build darwin dragonfly freebsd linux netbsd openbsd solaris | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| import ( | ||||
| 	"syscall" | ||||
| ) | ||||
| 
 | ||||
| // ioComplete checks the flags and result of a syscall, to be used as return | ||||
| // value in a syscall.RawConn.Read or Write callback. | ||||
| func ioComplete(flags int, operr error) bool { | ||||
| 	if flags&syscall.MSG_DONTWAIT != 0 { | ||||
| 		// Caller explicitly said don't wait, so always return immediately. | ||||
| 		return true | ||||
| 	} | ||||
| 	if operr == syscall.EAGAIN || operr == syscall.EWOULDBLOCK { | ||||
| 		// No data available, block for I/O and try again. | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
							
								
								
									
										22
									
								
								vendor/golang.org/x/net/internal/socket/complete_nodontwait.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/golang.org/x/net/internal/socket/complete_nodontwait.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| // Copyright 2021 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| //go:build aix || windows || zos | ||||
| // +build aix windows zos | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| import ( | ||||
| 	"syscall" | ||||
| ) | ||||
| 
 | ||||
| // ioComplete checks the flags and result of a syscall, to be used as return | ||||
| // value in a syscall.RawConn.Read or Write callback. | ||||
| func ioComplete(flags int, operr error) bool { | ||||
| 	if operr == syscall.EAGAIN || operr == syscall.EWOULDBLOCK { | ||||
| 		// No data available, block for I/O and try again. | ||||
| 		return false | ||||
| 	} | ||||
| 	return true | ||||
| } | ||||
							
								
								
									
										8
									
								
								vendor/golang.org/x/net/internal/socket/empty.s
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vendor/golang.org/x/net/internal/socket/empty.s
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| // Copyright 2018 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| //go:build darwin && go1.12 | ||||
| // +build darwin,go1.12 | ||||
| 
 | ||||
| // This exists solely so we can linkname in symbols from syscall. | ||||
							
								
								
									
										32
									
								
								vendor/golang.org/x/net/internal/socket/error_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/golang.org/x/net/internal/socket/error_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos | ||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
							
								
								
									
										26
									
								
								vendor/golang.org/x/net/internal/socket/error_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/golang.org/x/net/internal/socket/error_windows.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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 | ||||
| } | ||||
							
								
								
									
										20
									
								
								vendor/golang.org/x/net/internal/socket/iovec_32bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/golang.org/x/net/internal/socket/iovec_32bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build (arm || mips || mipsle || 386 || ppc) && (darwin || dragonfly || freebsd || linux || netbsd || openbsd) | ||||
| // +build arm mips mipsle 386 ppc | ||||
| // +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) | ||||
| } | ||||
							
								
								
									
										20
									
								
								vendor/golang.org/x/net/internal/socket/iovec_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								vendor/golang.org/x/net/internal/socket/iovec_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build (arm64 || amd64 || loong64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos) | ||||
| // +build arm64 amd64 loong64 ppc64 ppc64le mips64 mips64le riscv64 s390x | ||||
| // +build aix darwin dragonfly freebsd linux netbsd openbsd zos | ||||
| 
 | ||||
| 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) | ||||
| } | ||||
							
								
								
									
										19
									
								
								vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								vendor/golang.org/x/net/internal/socket/iovec_solaris_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build amd64 && solaris | ||||
| // +build amd64,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) | ||||
| } | ||||
							
								
								
									
										12
									
								
								vendor/golang.org/x/net/internal/socket/iovec_stub.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/golang.org/x/net/internal/socket/iovec_stub.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +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. | ||||
| 
 | ||||
| //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos | ||||
| // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| type iovec struct{} | ||||
| 
 | ||||
| func (v *iovec) set(b []byte) {} | ||||
							
								
								
									
										22
									
								
								vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/golang.org/x/net/internal/socket/mmsghdr_stub.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build !aix && !linux && !netbsd | ||||
| // +build !aix,!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 | ||||
| } | ||||
							
								
								
									
										180
									
								
								vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								vendor/golang.org/x/net/internal/socket/mmsghdr_unix.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,180 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build aix || linux || netbsd | ||||
| // +build aix linux netbsd | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| import ( | ||||
| 	"net" | ||||
| 	"os" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| ) | ||||
| 
 | ||||
| type mmsghdrs []mmsghdr | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| // mmsghdrsPacker packs Message-slices into mmsghdrs (re-)using pre-allocated buffers. | ||||
| type mmsghdrsPacker struct { | ||||
| 	// hs are the pre-allocated mmsghdrs. | ||||
| 	hs mmsghdrs | ||||
| 	// sockaddrs is the pre-allocated buffer for the Hdr.Name buffers. | ||||
| 	// We use one large buffer for all messages and slice it up. | ||||
| 	sockaddrs []byte | ||||
| 	// vs are the pre-allocated iovecs. | ||||
| 	// We allocate one large buffer for all messages and slice it up. This allows to reuse the buffer | ||||
| 	// if the number of buffers per message is distributed differently between calls. | ||||
| 	vs []iovec | ||||
| } | ||||
| 
 | ||||
| func (p *mmsghdrsPacker) prepare(ms []Message) { | ||||
| 	n := len(ms) | ||||
| 	if n <= cap(p.hs) { | ||||
| 		p.hs = p.hs[:n] | ||||
| 	} else { | ||||
| 		p.hs = make(mmsghdrs, n) | ||||
| 	} | ||||
| 	if n*sizeofSockaddrInet6 <= cap(p.sockaddrs) { | ||||
| 		p.sockaddrs = p.sockaddrs[:n*sizeofSockaddrInet6] | ||||
| 	} else { | ||||
| 		p.sockaddrs = make([]byte, n*sizeofSockaddrInet6) | ||||
| 	} | ||||
| 
 | ||||
| 	nb := 0 | ||||
| 	for _, m := range ms { | ||||
| 		nb += len(m.Buffers) | ||||
| 	} | ||||
| 	if nb <= cap(p.vs) { | ||||
| 		p.vs = p.vs[:nb] | ||||
| 	} else { | ||||
| 		p.vs = make([]iovec, nb) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (p *mmsghdrsPacker) pack(ms []Message, parseFn func([]byte, string) (net.Addr, error), marshalFn func(net.Addr, []byte) int) mmsghdrs { | ||||
| 	p.prepare(ms) | ||||
| 	hs := p.hs | ||||
| 	vsRest := p.vs | ||||
| 	saRest := p.sockaddrs | ||||
| 	for i := range hs { | ||||
| 		nvs := len(ms[i].Buffers) | ||||
| 		vs := vsRest[:nvs] | ||||
| 		vsRest = vsRest[nvs:] | ||||
| 
 | ||||
| 		var sa []byte | ||||
| 		if parseFn != nil { | ||||
| 			sa = saRest[:sizeofSockaddrInet6] | ||||
| 			saRest = saRest[sizeofSockaddrInet6:] | ||||
| 		} else if marshalFn != nil { | ||||
| 			n := marshalFn(ms[i].Addr, saRest) | ||||
| 			if n > 0 { | ||||
| 				sa = saRest[:n] | ||||
| 				saRest = saRest[n:] | ||||
| 			} | ||||
| 		} | ||||
| 		hs[i].Hdr.pack(vs, ms[i].Buffers, ms[i].OOB, sa) | ||||
| 	} | ||||
| 	return hs | ||||
| } | ||||
| 
 | ||||
| // syscaller is a helper to invoke recvmmsg and sendmmsg via the RawConn.Read/Write interface. | ||||
| // It is reusable, to amortize the overhead of allocating a closure for the function passed to | ||||
| // RawConn.Read/Write. | ||||
| type syscaller struct { | ||||
| 	n     int | ||||
| 	operr error | ||||
| 	hs    mmsghdrs | ||||
| 	flags int | ||||
| 
 | ||||
| 	boundRecvmmsgF func(uintptr) bool | ||||
| 	boundSendmmsgF func(uintptr) bool | ||||
| } | ||||
| 
 | ||||
| func (r *syscaller) init() { | ||||
| 	r.boundRecvmmsgF = r.recvmmsgF | ||||
| 	r.boundSendmmsgF = r.sendmmsgF | ||||
| } | ||||
| 
 | ||||
| func (r *syscaller) recvmmsg(c syscall.RawConn, hs mmsghdrs, flags int) (int, error) { | ||||
| 	r.n = 0 | ||||
| 	r.operr = nil | ||||
| 	r.hs = hs | ||||
| 	r.flags = flags | ||||
| 	if err := c.Read(r.boundRecvmmsgF); err != nil { | ||||
| 		return r.n, err | ||||
| 	} | ||||
| 	if r.operr != nil { | ||||
| 		return r.n, os.NewSyscallError("recvmmsg", r.operr) | ||||
| 	} | ||||
| 	return r.n, nil | ||||
| } | ||||
| 
 | ||||
| func (r *syscaller) recvmmsgF(s uintptr) bool { | ||||
| 	r.n, r.operr = recvmmsg(s, r.hs, r.flags) | ||||
| 	return ioComplete(r.flags, r.operr) | ||||
| } | ||||
| 
 | ||||
| func (r *syscaller) sendmmsg(c syscall.RawConn, hs mmsghdrs, flags int) (int, error) { | ||||
| 	r.n = 0 | ||||
| 	r.operr = nil | ||||
| 	r.hs = hs | ||||
| 	r.flags = flags | ||||
| 	if err := c.Write(r.boundSendmmsgF); err != nil { | ||||
| 		return r.n, err | ||||
| 	} | ||||
| 	if r.operr != nil { | ||||
| 		return r.n, os.NewSyscallError("sendmmsg", r.operr) | ||||
| 	} | ||||
| 	return r.n, nil | ||||
| } | ||||
| 
 | ||||
| func (r *syscaller) sendmmsgF(s uintptr) bool { | ||||
| 	r.n, r.operr = sendmmsg(s, r.hs, r.flags) | ||||
| 	return ioComplete(r.flags, r.operr) | ||||
| } | ||||
| 
 | ||||
| // mmsgTmps holds reusable temporary helpers for recvmmsg and sendmmsg. | ||||
| type mmsgTmps struct { | ||||
| 	packer    mmsghdrsPacker | ||||
| 	syscaller syscaller | ||||
| } | ||||
| 
 | ||||
| var defaultMmsgTmpsPool = mmsgTmpsPool{ | ||||
| 	p: sync.Pool{ | ||||
| 		New: func() interface{} { | ||||
| 			tmps := new(mmsgTmps) | ||||
| 			tmps.syscaller.init() | ||||
| 			return tmps | ||||
| 		}, | ||||
| 	}, | ||||
| } | ||||
| 
 | ||||
| type mmsgTmpsPool struct { | ||||
| 	p sync.Pool | ||||
| } | ||||
| 
 | ||||
| func (p *mmsgTmpsPool) Get() *mmsgTmps { | ||||
| 	return p.p.Get().(*mmsgTmps) | ||||
| } | ||||
| 
 | ||||
| func (p *mmsgTmpsPool) Put(tmps *mmsgTmps) { | ||||
| 	p.p.Put(tmps) | ||||
| } | ||||
							
								
								
									
										40
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_bsd.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd | ||||
| // +build aix 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) | ||||
| } | ||||
							
								
								
									
										17
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_bsdvar.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build aix || darwin || dragonfly || freebsd || netbsd | ||||
| // +build aix 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) | ||||
| } | ||||
							
								
								
									
										39
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_linux.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_linux.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| 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)) | ||||
| 	} else { | ||||
| 		h.Name = nil | ||||
| 		h.Namelen = 0 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_linux_32bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build (arm || mips || mipsle || 386 || ppc) && linux | ||||
| // +build arm mips mipsle 386 ppc | ||||
| // +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)) | ||||
| } | ||||
							
								
								
									
										25
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_linux_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build (arm64 || amd64 || loong64 || ppc64 || ppc64le || mips64 || mips64le || riscv64 || s390x) && linux | ||||
| // +build arm64 amd64 loong64 ppc64 ppc64le mips64 mips64le riscv64 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)) | ||||
| } | ||||
							
								
								
									
										14
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_openbsd.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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) | ||||
| } | ||||
							
								
								
									
										36
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_solaris_64bit.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -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. | ||||
| 
 | ||||
| //go:build amd64 && solaris | ||||
| // +build amd64,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[:])) | ||||
| } | ||||
							
								
								
									
										15
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_stub.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_stub.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | |||
| // 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. | ||||
| 
 | ||||
| //go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris && !zos | ||||
| // +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris,!zos | ||||
| 
 | ||||
| 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 } | ||||
							
								
								
									
										36
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_zos_s390x.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								vendor/golang.org/x/net/internal/socket/msghdr_zos_s390x.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| // Copyright 2020 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| //go:build s390x && zos | ||||
| // +build s390x,zos | ||||
| 
 | ||||
| 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.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) controllen() int { | ||||
| 	return int(h.Controllen) | ||||
| } | ||||
| 
 | ||||
| func (h *msghdr) flags() int { | ||||
| 	return int(h.Flags) | ||||
| } | ||||
							
								
								
									
										13
									
								
								vendor/golang.org/x/net/internal/socket/norace.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/golang.org/x/net/internal/socket/norace.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | |||
| // Copyright 2019 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| //go:build !race | ||||
| // +build !race | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| func (m *Message) raceRead() { | ||||
| } | ||||
| func (m *Message) raceWrite() { | ||||
| } | ||||
							
								
								
									
										38
									
								
								vendor/golang.org/x/net/internal/socket/race.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								vendor/golang.org/x/net/internal/socket/race.go
									
										
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| // Copyright 2019 The Go Authors. All rights reserved. | ||||
| // Use of this source code is governed by a BSD-style | ||||
| // license that can be found in the LICENSE file. | ||||
| 
 | ||||
| //go:build race | ||||
| // +build race | ||||
| 
 | ||||
| package socket | ||||
| 
 | ||||
| import ( | ||||
| 	"runtime" | ||||
| 	"unsafe" | ||||
| ) | ||||
| 
 | ||||
| // This package reads and writes the Message buffers using a | ||||
| // direct system call, which the race detector can't see. | ||||
| // These functions tell the race detector what is going on during the syscall. | ||||
| 
 | ||||
| func (m *Message) raceRead() { | ||||
| 	for _, b := range m.Buffers { | ||||
| 		if len(b) > 0 { | ||||
| 			runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b)) | ||||
| 		} | ||||
| 	} | ||||
| 	if b := m.OOB; len(b) > 0 { | ||||
| 		runtime.RaceReadRange(unsafe.Pointer(&b[0]), len(b)) | ||||
| 	} | ||||
| } | ||||
| func (m *Message) raceWrite() { | ||||
| 	for _, b := range m.Buffers { | ||||
| 		if len(b) > 0 { | ||||
| 			runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b)) | ||||
| 		} | ||||
| 	} | ||||
| 	if b := m.OOB; len(b) > 0 { | ||||
| 		runtime.RaceWriteRange(unsafe.Pointer(&b[0]), len(b)) | ||||
| 	} | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue