mirror of https://github.com/kubernetes/kops.git
				
				
				
			Add staticcheck to vendor directory
This commit is contained in:
		
							parent
							
								
									ac36e9c41d
								
							
						
					
					
						commit
						a8f0c49346
					
				
							
								
								
									
										3
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										3
									
								
								go.mod
								
								
								
								
							|  | @ -116,12 +116,13 @@ require ( | ||||||
| 	github.com/vmware/govmomi v0.20.1 | 	github.com/vmware/govmomi v0.20.1 | ||||||
| 	github.com/weaveworks/mesh v0.0.0-20170419100114-1f158d31de55 | 	github.com/weaveworks/mesh v0.0.0-20170419100114-1f158d31de55 | ||||||
| 	go.uber.org/zap v1.9.1 | 	go.uber.org/zap v1.9.1 | ||||||
| 	golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 | 	golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 | ||||||
| 	golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc | 	golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc | ||||||
| 	golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a | 	golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a | ||||||
| 	google.golang.org/api v0.0.0-20181220000619-583d854617af | 	google.golang.org/api v0.0.0-20181220000619-583d854617af | ||||||
| 	gopkg.in/gcfg.v1 v1.2.0 | 	gopkg.in/gcfg.v1 v1.2.0 | ||||||
| 	gopkg.in/yaml.v2 v2.2.2 | 	gopkg.in/yaml.v2 v2.2.2 | ||||||
|  | 	honnef.co/go/tools v0.0.1-2019.2.3 | ||||||
| 	k8s.io/api v0.0.0 | 	k8s.io/api v0.0.0 | ||||||
| 	k8s.io/apimachinery v0.0.0 | 	k8s.io/apimachinery v0.0.0 | ||||||
| 	k8s.io/cli-runtime v0.0.0 | 	k8s.io/cli-runtime v0.0.0 | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										14
									
								
								go.sum
								
								
								
								
							|  | @ -188,6 +188,7 @@ github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASu | ||||||
| github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= | github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= | ||||||
| github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= | github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck= | ||||||
| github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= | github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= | ||||||
|  | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= | ||||||
| github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||||
| github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= | github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= | ||||||
| github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||||
|  | @ -250,6 +251,7 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 | ||||||
| github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= | ||||||
| github.com/kardianos/osext v0.0.0-20150410034420-8fef92e41e22/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= | github.com/kardianos/osext v0.0.0-20150410034420-8fef92e41e22/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= | ||||||
| github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= | github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= | ||||||
|  | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | ||||||
| github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= | github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= | ||||||
| github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= | ||||||
| github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 h1:YUrU1/jxRqnt0PSrKj1Uj/wEjk/fjnE80QFfi2Zlj7Q= | github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 h1:YUrU1/jxRqnt0PSrKj1Uj/wEjk/fjnE80QFfi2Zlj7Q= | ||||||
|  | @ -342,6 +344,7 @@ github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R | ||||||
| github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI= | github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI= | ||||||
| github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= | github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= | ||||||
| github.com/robfig/cron v0.0.0-20170309132418-df38d32658d8/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= | github.com/robfig/cron v0.0.0-20170309132418-df38d32658d8/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= | ||||||
|  | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= | ||||||
| github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= | github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= | ||||||
| github.com/russross/blackfriday v0.0.0-20151117072312-300106c228d5 h1:+6eORf9Bt4C3Wjt91epyu6wvLW+P6+AEODb6uKgO+4g= | github.com/russross/blackfriday v0.0.0-20151117072312-300106c228d5 h1:+6eORf9Bt4C3Wjt91epyu6wvLW+P6+AEODb6uKgO+4g= | ||||||
| github.com/russross/blackfriday v0.0.0-20151117072312-300106c228d5/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= | github.com/russross/blackfriday v0.0.0-20151117072312-300106c228d5/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= | ||||||
|  | @ -417,17 +420,21 @@ golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnf | ||||||
| golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= | ||||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= | ||||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||||
|  | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk= | ||||||
|  | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||||
| golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||||
| golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= | golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= | ||||||
| golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= | ||||||
| golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | ||||||
| golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= | ||||||
|  | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= | ||||||
| golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||||
|  | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||||
| golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68= | golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68= | ||||||
| golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||||
|  | @ -446,6 +453,8 @@ golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5h | ||||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||||
| golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc= | golang.org/x/sys v0.0.0-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc= | ||||||
| golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= | ||||||
|  | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= | golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU= | ||||||
| golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||||||
|  | @ -459,6 +468,8 @@ golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGm | ||||||
| golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||||
| golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg= | ||||||
| golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= | ||||||
|  | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac h1:MQEvx39qSf8vyrx3XRaOe+j1UDIzKwkYOVObRgGPVqI= | ||||||
|  | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | ||||||
| gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= | gomodules.xyz/jsonpatch/v2 v2.0.1 h1:xyiBuvkD2g5n7cYzx6u2sxQvsAy4QJsZFCzGVdzOXZ0= | ||||||
| gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= | gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= | ||||||
| gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= | gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= | ||||||
|  | @ -477,6 +488,7 @@ google.golang.org/grpc v1.13.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmE | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
| gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= | ||||||
| gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
|  | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= | ||||||
| gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= | ||||||
| gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | ||||||
| gopkg.in/gcfg.v1 v1.2.0 h1:0HIbH907iBTAntm+88IJV2qmJALDAh8sPekI9Vc1fm0= | gopkg.in/gcfg.v1 v1.2.0 h1:0HIbH907iBTAntm+88IJV2qmJALDAh8sPekI9Vc1fm0= | ||||||
|  | @ -499,6 +511,8 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | ||||||
| gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||||
| gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= | gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= | ||||||
| gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= | ||||||
|  | honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= | ||||||
|  | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= | ||||||
| k8s.io/api v0.0.0-20190819141258-3544db3b9e44 h1:7Gz7/nQ7X2qmPXMyN0bNq7Zm9Uip+UnFuMZTd2l3vms= | k8s.io/api v0.0.0-20190819141258-3544db3b9e44 h1:7Gz7/nQ7X2qmPXMyN0bNq7Zm9Uip+UnFuMZTd2l3vms= | ||||||
| k8s.io/api v0.0.0-20190819141258-3544db3b9e44/go.mod h1:AOxZTnaXR/xiarlQL0JUfwQPxjmKDvVYoRp58cA7lUo= | k8s.io/api v0.0.0-20190819141258-3544db3b9e44/go.mod h1:AOxZTnaXR/xiarlQL0JUfwQPxjmKDvVYoRp58cA7lUo= | ||||||
| k8s.io/apiextensions-apiserver v0.0.0-20190819143637-0dbe462fe92d h1:OurCXHUvzXu5J01qotK6uF1KRTX4SGXjrnolt+S9QZs= | k8s.io/apiextensions-apiserver v0.0.0-20190819143637-0dbe462fe92d h1:OurCXHUvzXu5J01qotK6uF1KRTX4SGXjrnolt+S9QZs= | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								tools.go
								
								
								
								
							
							
						
						
									
										2
									
								
								tools.go
								
								
								
								
							|  | @ -25,4 +25,6 @@ import ( | ||||||
| 	_ "github.com/jteeuwen/go-bindata/go-bindata" | 	_ "github.com/jteeuwen/go-bindata/go-bindata" | ||||||
| 
 | 
 | ||||||
| 	_ "github.com/client9/misspell/cmd/misspell" | 	_ "github.com/client9/misspell/cmd/misspell" | ||||||
|  | 
 | ||||||
|  | 	_ "honnef.co/go/tools/cmd/staticcheck" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | @ -0,0 +1,5 @@ | ||||||
|  | TAGS | ||||||
|  | tags | ||||||
|  | .*.swp | ||||||
|  | tomlcheck/tomlcheck | ||||||
|  | toml.test | ||||||
|  | @ -0,0 +1,15 @@ | ||||||
|  | language: go | ||||||
|  | go: | ||||||
|  |   - 1.1 | ||||||
|  |   - 1.2 | ||||||
|  |   - 1.3 | ||||||
|  |   - 1.4 | ||||||
|  |   - 1.5 | ||||||
|  |   - 1.6 | ||||||
|  |   - tip | ||||||
|  | install: | ||||||
|  |   - go install ./... | ||||||
|  |   - go get github.com/BurntSushi/toml-test | ||||||
|  | script: | ||||||
|  |   - export PATH="$PATH:$HOME/gopath/bin" | ||||||
|  |   - make test | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | load("@io_bazel_rules_go//go:def.bzl", "go_library") | ||||||
|  | 
 | ||||||
|  | go_library( | ||||||
|  |     name = "go_default_library", | ||||||
|  |     srcs = [ | ||||||
|  |         "decode.go", | ||||||
|  |         "decode_meta.go", | ||||||
|  |         "doc.go", | ||||||
|  |         "encode.go", | ||||||
|  |         "encoding_types.go", | ||||||
|  |         "encoding_types_1.1.go", | ||||||
|  |         "lex.go", | ||||||
|  |         "parse.go", | ||||||
|  |         "type_check.go", | ||||||
|  |         "type_fields.go", | ||||||
|  |     ], | ||||||
|  |     importmap = "k8s.io/kops/vendor/github.com/BurntSushi/toml", | ||||||
|  |     importpath = "github.com/BurntSushi/toml", | ||||||
|  |     visibility = ["//visibility:public"], | ||||||
|  | ) | ||||||
|  | @ -0,0 +1,3 @@ | ||||||
|  | Compatible with TOML version | ||||||
|  | [v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md) | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,21 @@ | ||||||
|  | The MIT License (MIT) | ||||||
|  | 
 | ||||||
|  | Copyright (c) 2013 TOML authors | ||||||
|  | 
 | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||||
|  | furnished to do so, subject to the following conditions: | ||||||
|  | 
 | ||||||
|  | The above copyright notice and this permission notice shall be included in | ||||||
|  | all copies or substantial portions of the Software. | ||||||
|  | 
 | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||||
|  | THE SOFTWARE. | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | install: | ||||||
|  | 	go install ./... | ||||||
|  | 
 | ||||||
|  | test: install | ||||||
|  | 	go test -v | ||||||
|  | 	toml-test toml-test-decoder | ||||||
|  | 	toml-test -encoder toml-test-encoder | ||||||
|  | 
 | ||||||
|  | fmt: | ||||||
|  | 	gofmt -w *.go */*.go | ||||||
|  | 	colcheck *.go */*.go | ||||||
|  | 
 | ||||||
|  | tags: | ||||||
|  | 	find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS | ||||||
|  | 
 | ||||||
|  | push: | ||||||
|  | 	git push origin master | ||||||
|  | 	git push github master | ||||||
|  | 
 | ||||||
|  | @ -0,0 +1,218 @@ | ||||||
|  | ## TOML parser and encoder for Go with reflection | ||||||
|  | 
 | ||||||
|  | TOML stands for Tom's Obvious, Minimal Language. This Go package provides a | ||||||
|  | reflection interface similar to Go's standard library `json` and `xml` | ||||||
|  | packages. This package also supports the `encoding.TextUnmarshaler` and | ||||||
|  | `encoding.TextMarshaler` interfaces so that you can define custom data | ||||||
|  | representations. (There is an example of this below.) | ||||||
|  | 
 | ||||||
|  | Spec: https://github.com/toml-lang/toml | ||||||
|  | 
 | ||||||
|  | Compatible with TOML version | ||||||
|  | [v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) | ||||||
|  | 
 | ||||||
|  | Documentation: https://godoc.org/github.com/BurntSushi/toml | ||||||
|  | 
 | ||||||
|  | Installation: | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | go get github.com/BurntSushi/toml | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Try the toml validator: | ||||||
|  | 
 | ||||||
|  | ```bash | ||||||
|  | go get github.com/BurntSushi/toml/cmd/tomlv | ||||||
|  | tomlv some-toml-file.toml | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | [](https://travis-ci.org/BurntSushi/toml) [](https://godoc.org/github.com/BurntSushi/toml) | ||||||
|  | 
 | ||||||
|  | ### Testing | ||||||
|  | 
 | ||||||
|  | This package passes all tests in | ||||||
|  | [toml-test](https://github.com/BurntSushi/toml-test) for both the decoder | ||||||
|  | and the encoder. | ||||||
|  | 
 | ||||||
|  | ### Examples | ||||||
|  | 
 | ||||||
|  | This package works similarly to how the Go standard library handles `XML` | ||||||
|  | and `JSON`. Namely, data is loaded into Go values via reflection. | ||||||
|  | 
 | ||||||
|  | For the simplest example, consider some TOML file as just a list of keys | ||||||
|  | and values: | ||||||
|  | 
 | ||||||
|  | ```toml | ||||||
|  | Age = 25 | ||||||
|  | Cats = [ "Cauchy", "Plato" ] | ||||||
|  | Pi = 3.14 | ||||||
|  | Perfection = [ 6, 28, 496, 8128 ] | ||||||
|  | DOB = 1987-07-05T05:45:00Z | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Which could be defined in Go as: | ||||||
|  | 
 | ||||||
|  | ```go | ||||||
|  | type Config struct { | ||||||
|  |   Age int | ||||||
|  |   Cats []string | ||||||
|  |   Pi float64 | ||||||
|  |   Perfection []int | ||||||
|  |   DOB time.Time // requires `import time` | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | And then decoded with: | ||||||
|  | 
 | ||||||
|  | ```go | ||||||
|  | var conf Config | ||||||
|  | if _, err := toml.Decode(tomlData, &conf); err != nil { | ||||||
|  |   // handle error | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | You can also use struct tags if your struct field name doesn't map to a TOML | ||||||
|  | key value directly: | ||||||
|  | 
 | ||||||
|  | ```toml | ||||||
|  | some_key_NAME = "wat" | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ```go | ||||||
|  | type TOML struct { | ||||||
|  |   ObscureKey string `toml:"some_key_NAME"` | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### Using the `encoding.TextUnmarshaler` interface | ||||||
|  | 
 | ||||||
|  | Here's an example that automatically parses duration strings into | ||||||
|  | `time.Duration` values: | ||||||
|  | 
 | ||||||
|  | ```toml | ||||||
|  | [[song]] | ||||||
|  | name = "Thunder Road" | ||||||
|  | duration = "4m49s" | ||||||
|  | 
 | ||||||
|  | [[song]] | ||||||
|  | name = "Stairway to Heaven" | ||||||
|  | duration = "8m03s" | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Which can be decoded with: | ||||||
|  | 
 | ||||||
|  | ```go | ||||||
|  | type song struct { | ||||||
|  |   Name     string | ||||||
|  |   Duration duration | ||||||
|  | } | ||||||
|  | type songs struct { | ||||||
|  |   Song []song | ||||||
|  | } | ||||||
|  | var favorites songs | ||||||
|  | if _, err := toml.Decode(blob, &favorites); err != nil { | ||||||
|  |   log.Fatal(err) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | for _, s := range favorites.Song { | ||||||
|  |   fmt.Printf("%s (%s)\n", s.Name, s.Duration) | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | And you'll also need a `duration` type that satisfies the | ||||||
|  | `encoding.TextUnmarshaler` interface: | ||||||
|  | 
 | ||||||
|  | ```go | ||||||
|  | type duration struct { | ||||||
|  | 	time.Duration | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (d *duration) UnmarshalText(text []byte) error { | ||||||
|  | 	var err error | ||||||
|  | 	d.Duration, err = time.ParseDuration(string(text)) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | ### More complex usage | ||||||
|  | 
 | ||||||
|  | Here's an example of how to load the example from the official spec page: | ||||||
|  | 
 | ||||||
|  | ```toml | ||||||
|  | # This is a TOML document. Boom. | ||||||
|  | 
 | ||||||
|  | title = "TOML Example" | ||||||
|  | 
 | ||||||
|  | [owner] | ||||||
|  | name = "Tom Preston-Werner" | ||||||
|  | organization = "GitHub" | ||||||
|  | bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." | ||||||
|  | dob = 1979-05-27T07:32:00Z # First class dates? Why not? | ||||||
|  | 
 | ||||||
|  | [database] | ||||||
|  | server = "192.168.1.1" | ||||||
|  | ports = [ 8001, 8001, 8002 ] | ||||||
|  | connection_max = 5000 | ||||||
|  | enabled = true | ||||||
|  | 
 | ||||||
|  | [servers] | ||||||
|  | 
 | ||||||
|  |   # You can indent as you please. Tabs or spaces. TOML don't care. | ||||||
|  |   [servers.alpha] | ||||||
|  |   ip = "10.0.0.1" | ||||||
|  |   dc = "eqdc10" | ||||||
|  | 
 | ||||||
|  |   [servers.beta] | ||||||
|  |   ip = "10.0.0.2" | ||||||
|  |   dc = "eqdc10" | ||||||
|  | 
 | ||||||
|  | [clients] | ||||||
|  | data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it | ||||||
|  | 
 | ||||||
|  | # Line breaks are OK when inside arrays | ||||||
|  | hosts = [ | ||||||
|  |   "alpha", | ||||||
|  |   "omega" | ||||||
|  | ] | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | And the corresponding Go types are: | ||||||
|  | 
 | ||||||
|  | ```go | ||||||
|  | type tomlConfig struct { | ||||||
|  | 	Title string | ||||||
|  | 	Owner ownerInfo | ||||||
|  | 	DB database `toml:"database"` | ||||||
|  | 	Servers map[string]server | ||||||
|  | 	Clients clients | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type ownerInfo struct { | ||||||
|  | 	Name string | ||||||
|  | 	Org string `toml:"organization"` | ||||||
|  | 	Bio string | ||||||
|  | 	DOB time.Time | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type database struct { | ||||||
|  | 	Server string | ||||||
|  | 	Ports []int | ||||||
|  | 	ConnMax int `toml:"connection_max"` | ||||||
|  | 	Enabled bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type server struct { | ||||||
|  | 	IP string | ||||||
|  | 	DC string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type clients struct { | ||||||
|  | 	Data [][]interface{} | ||||||
|  | 	Hosts []string | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | Note that a case insensitive match will be tried if an exact match can't be | ||||||
|  | found. | ||||||
|  | 
 | ||||||
|  | A working example of the above can be found in `_examples/example.{go,toml}`. | ||||||
|  | @ -0,0 +1,509 @@ | ||||||
|  | package toml | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"math" | ||||||
|  | 	"reflect" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func e(format string, args ...interface{}) error { | ||||||
|  | 	return fmt.Errorf("toml: "+format, args...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Unmarshaler is the interface implemented by objects that can unmarshal a
 | ||||||
|  | // TOML description of themselves.
 | ||||||
|  | type Unmarshaler interface { | ||||||
|  | 	UnmarshalTOML(interface{}) error | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Unmarshal decodes the contents of `p` in TOML format into a pointer `v`.
 | ||||||
|  | func Unmarshal(p []byte, v interface{}) error { | ||||||
|  | 	_, err := Decode(string(p), v) | ||||||
|  | 	return err | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Primitive is a TOML value that hasn't been decoded into a Go value.
 | ||||||
|  | // When using the various `Decode*` functions, the type `Primitive` may
 | ||||||
|  | // be given to any value, and its decoding will be delayed.
 | ||||||
|  | //
 | ||||||
|  | // A `Primitive` value can be decoded using the `PrimitiveDecode` function.
 | ||||||
|  | //
 | ||||||
|  | // The underlying representation of a `Primitive` value is subject to change.
 | ||||||
|  | // Do not rely on it.
 | ||||||
|  | //
 | ||||||
|  | // N.B. Primitive values are still parsed, so using them will only avoid
 | ||||||
|  | // the overhead of reflection. They can be useful when you don't know the
 | ||||||
|  | // exact type of TOML data until run time.
 | ||||||
|  | type Primitive struct { | ||||||
|  | 	undecoded interface{} | ||||||
|  | 	context   Key | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DEPRECATED!
 | ||||||
|  | //
 | ||||||
|  | // Use MetaData.PrimitiveDecode instead.
 | ||||||
|  | func PrimitiveDecode(primValue Primitive, v interface{}) error { | ||||||
|  | 	md := MetaData{decoded: make(map[string]bool)} | ||||||
|  | 	return md.unify(primValue.undecoded, rvalue(v)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // PrimitiveDecode is just like the other `Decode*` functions, except it
 | ||||||
|  | // decodes a TOML value that has already been parsed. Valid primitive values
 | ||||||
|  | // can *only* be obtained from values filled by the decoder functions,
 | ||||||
|  | // including this method. (i.e., `v` may contain more `Primitive`
 | ||||||
|  | // values.)
 | ||||||
|  | //
 | ||||||
|  | // Meta data for primitive values is included in the meta data returned by
 | ||||||
|  | // the `Decode*` functions with one exception: keys returned by the Undecoded
 | ||||||
|  | // method will only reflect keys that were decoded. Namely, any keys hidden
 | ||||||
|  | // behind a Primitive will be considered undecoded. Executing this method will
 | ||||||
|  | // update the undecoded keys in the meta data. (See the example.)
 | ||||||
|  | func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { | ||||||
|  | 	md.context = primValue.context | ||||||
|  | 	defer func() { md.context = nil }() | ||||||
|  | 	return md.unify(primValue.undecoded, rvalue(v)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Decode will decode the contents of `data` in TOML format into a pointer
 | ||||||
|  | // `v`.
 | ||||||
|  | //
 | ||||||
|  | // TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be
 | ||||||
|  | // used interchangeably.)
 | ||||||
|  | //
 | ||||||
|  | // TOML arrays of tables correspond to either a slice of structs or a slice
 | ||||||
|  | // of maps.
 | ||||||
|  | //
 | ||||||
|  | // TOML datetimes correspond to Go `time.Time` values.
 | ||||||
|  | //
 | ||||||
|  | // All other TOML types (float, string, int, bool and array) correspond
 | ||||||
|  | // to the obvious Go types.
 | ||||||
|  | //
 | ||||||
|  | // An exception to the above rules is if a type implements the
 | ||||||
|  | // encoding.TextUnmarshaler interface. In this case, any primitive TOML value
 | ||||||
|  | // (floats, strings, integers, booleans and datetimes) will be converted to
 | ||||||
|  | // a byte string and given to the value's UnmarshalText method. See the
 | ||||||
|  | // Unmarshaler example for a demonstration with time duration strings.
 | ||||||
|  | //
 | ||||||
|  | // Key mapping
 | ||||||
|  | //
 | ||||||
|  | // TOML keys can map to either keys in a Go map or field names in a Go
 | ||||||
|  | // struct. The special `toml` struct tag may be used to map TOML keys to
 | ||||||
|  | // struct fields that don't match the key name exactly. (See the example.)
 | ||||||
|  | // A case insensitive match to struct names will be tried if an exact match
 | ||||||
|  | // can't be found.
 | ||||||
|  | //
 | ||||||
|  | // The mapping between TOML values and Go values is loose. That is, there
 | ||||||
|  | // may exist TOML values that cannot be placed into your representation, and
 | ||||||
|  | // there may be parts of your representation that do not correspond to
 | ||||||
|  | // TOML values. This loose mapping can be made stricter by using the IsDefined
 | ||||||
|  | // and/or Undecoded methods on the MetaData returned.
 | ||||||
|  | //
 | ||||||
|  | // This decoder will not handle cyclic types. If a cyclic type is passed,
 | ||||||
|  | // `Decode` will not terminate.
 | ||||||
|  | func Decode(data string, v interface{}) (MetaData, error) { | ||||||
|  | 	rv := reflect.ValueOf(v) | ||||||
|  | 	if rv.Kind() != reflect.Ptr { | ||||||
|  | 		return MetaData{}, e("Decode of non-pointer %s", reflect.TypeOf(v)) | ||||||
|  | 	} | ||||||
|  | 	if rv.IsNil() { | ||||||
|  | 		return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v)) | ||||||
|  | 	} | ||||||
|  | 	p, err := parse(data) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return MetaData{}, err | ||||||
|  | 	} | ||||||
|  | 	md := MetaData{ | ||||||
|  | 		p.mapping, p.types, p.ordered, | ||||||
|  | 		make(map[string]bool, len(p.ordered)), nil, | ||||||
|  | 	} | ||||||
|  | 	return md, md.unify(p.mapping, indirect(rv)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DecodeFile is just like Decode, except it will automatically read the
 | ||||||
|  | // contents of the file at `fpath` and decode it for you.
 | ||||||
|  | func DecodeFile(fpath string, v interface{}) (MetaData, error) { | ||||||
|  | 	bs, err := ioutil.ReadFile(fpath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return MetaData{}, err | ||||||
|  | 	} | ||||||
|  | 	return Decode(string(bs), v) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // DecodeReader is just like Decode, except it will consume all bytes
 | ||||||
|  | // from the reader and decode it for you.
 | ||||||
|  | func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { | ||||||
|  | 	bs, err := ioutil.ReadAll(r) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return MetaData{}, err | ||||||
|  | 	} | ||||||
|  | 	return Decode(string(bs), v) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // unify performs a sort of type unification based on the structure of `rv`,
 | ||||||
|  | // which is the client representation.
 | ||||||
|  | //
 | ||||||
|  | // Any type mismatch produces an error. Finding a type that we don't know
 | ||||||
|  | // how to handle produces an unsupported type error.
 | ||||||
|  | func (md *MetaData) unify(data interface{}, rv reflect.Value) error { | ||||||
|  | 
 | ||||||
|  | 	// Special case. Look for a `Primitive` value.
 | ||||||
|  | 	if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() { | ||||||
|  | 		// Save the undecoded data and the key context into the primitive
 | ||||||
|  | 		// value.
 | ||||||
|  | 		context := make(Key, len(md.context)) | ||||||
|  | 		copy(context, md.context) | ||||||
|  | 		rv.Set(reflect.ValueOf(Primitive{ | ||||||
|  | 			undecoded: data, | ||||||
|  | 			context:   context, | ||||||
|  | 		})) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Special case. Unmarshaler Interface support.
 | ||||||
|  | 	if rv.CanAddr() { | ||||||
|  | 		if v, ok := rv.Addr().Interface().(Unmarshaler); ok { | ||||||
|  | 			return v.UnmarshalTOML(data) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Special case. Handle time.Time values specifically.
 | ||||||
|  | 	// TODO: Remove this code when we decide to drop support for Go 1.1.
 | ||||||
|  | 	// This isn't necessary in Go 1.2 because time.Time satisfies the encoding
 | ||||||
|  | 	// interfaces.
 | ||||||
|  | 	if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) { | ||||||
|  | 		return md.unifyDatetime(data, rv) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Special case. Look for a value satisfying the TextUnmarshaler interface.
 | ||||||
|  | 	if v, ok := rv.Interface().(TextUnmarshaler); ok { | ||||||
|  | 		return md.unifyText(data, v) | ||||||
|  | 	} | ||||||
|  | 	// BUG(burntsushi)
 | ||||||
|  | 	// The behavior here is incorrect whenever a Go type satisfies the
 | ||||||
|  | 	// encoding.TextUnmarshaler interface but also corresponds to a TOML
 | ||||||
|  | 	// hash or array. In particular, the unmarshaler should only be applied
 | ||||||
|  | 	// to primitive TOML values. But at this point, it will be applied to
 | ||||||
|  | 	// all kinds of values and produce an incorrect error whenever those values
 | ||||||
|  | 	// are hashes or arrays (including arrays of tables).
 | ||||||
|  | 
 | ||||||
|  | 	k := rv.Kind() | ||||||
|  | 
 | ||||||
|  | 	// laziness
 | ||||||
|  | 	if k >= reflect.Int && k <= reflect.Uint64 { | ||||||
|  | 		return md.unifyInt(data, rv) | ||||||
|  | 	} | ||||||
|  | 	switch k { | ||||||
|  | 	case reflect.Ptr: | ||||||
|  | 		elem := reflect.New(rv.Type().Elem()) | ||||||
|  | 		err := md.unify(data, reflect.Indirect(elem)) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		rv.Set(elem) | ||||||
|  | 		return nil | ||||||
|  | 	case reflect.Struct: | ||||||
|  | 		return md.unifyStruct(data, rv) | ||||||
|  | 	case reflect.Map: | ||||||
|  | 		return md.unifyMap(data, rv) | ||||||
|  | 	case reflect.Array: | ||||||
|  | 		return md.unifyArray(data, rv) | ||||||
|  | 	case reflect.Slice: | ||||||
|  | 		return md.unifySlice(data, rv) | ||||||
|  | 	case reflect.String: | ||||||
|  | 		return md.unifyString(data, rv) | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		return md.unifyBool(data, rv) | ||||||
|  | 	case reflect.Interface: | ||||||
|  | 		// we only support empty interfaces.
 | ||||||
|  | 		if rv.NumMethod() > 0 { | ||||||
|  | 			return e("unsupported type %s", rv.Type()) | ||||||
|  | 		} | ||||||
|  | 		return md.unifyAnything(data, rv) | ||||||
|  | 	case reflect.Float32: | ||||||
|  | 		fallthrough | ||||||
|  | 	case reflect.Float64: | ||||||
|  | 		return md.unifyFloat64(data, rv) | ||||||
|  | 	} | ||||||
|  | 	return e("unsupported type %s", rv.Kind()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { | ||||||
|  | 	tmap, ok := mapping.(map[string]interface{}) | ||||||
|  | 	if !ok { | ||||||
|  | 		if mapping == nil { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		return e("type mismatch for %s: expected table but found %T", | ||||||
|  | 			rv.Type().String(), mapping) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for key, datum := range tmap { | ||||||
|  | 		var f *field | ||||||
|  | 		fields := cachedTypeFields(rv.Type()) | ||||||
|  | 		for i := range fields { | ||||||
|  | 			ff := &fields[i] | ||||||
|  | 			if ff.name == key { | ||||||
|  | 				f = ff | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 			if f == nil && strings.EqualFold(ff.name, key) { | ||||||
|  | 				f = ff | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if f != nil { | ||||||
|  | 			subv := rv | ||||||
|  | 			for _, i := range f.index { | ||||||
|  | 				subv = indirect(subv.Field(i)) | ||||||
|  | 			} | ||||||
|  | 			if isUnifiable(subv) { | ||||||
|  | 				md.decoded[md.context.add(key).String()] = true | ||||||
|  | 				md.context = append(md.context, key) | ||||||
|  | 				if err := md.unify(datum, subv); err != nil { | ||||||
|  | 					return err | ||||||
|  | 				} | ||||||
|  | 				md.context = md.context[0 : len(md.context)-1] | ||||||
|  | 			} else if f.name != "" { | ||||||
|  | 				// Bad user! No soup for you!
 | ||||||
|  | 				return e("cannot write unexported field %s.%s", | ||||||
|  | 					rv.Type().String(), f.name) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { | ||||||
|  | 	tmap, ok := mapping.(map[string]interface{}) | ||||||
|  | 	if !ok { | ||||||
|  | 		if tmap == nil { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		return badtype("map", mapping) | ||||||
|  | 	} | ||||||
|  | 	if rv.IsNil() { | ||||||
|  | 		rv.Set(reflect.MakeMap(rv.Type())) | ||||||
|  | 	} | ||||||
|  | 	for k, v := range tmap { | ||||||
|  | 		md.decoded[md.context.add(k).String()] = true | ||||||
|  | 		md.context = append(md.context, k) | ||||||
|  | 
 | ||||||
|  | 		rvkey := indirect(reflect.New(rv.Type().Key())) | ||||||
|  | 		rvval := reflect.Indirect(reflect.New(rv.Type().Elem())) | ||||||
|  | 		if err := md.unify(v, rvval); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		md.context = md.context[0 : len(md.context)-1] | ||||||
|  | 
 | ||||||
|  | 		rvkey.SetString(k) | ||||||
|  | 		rv.SetMapIndex(rvkey, rvval) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { | ||||||
|  | 	datav := reflect.ValueOf(data) | ||||||
|  | 	if datav.Kind() != reflect.Slice { | ||||||
|  | 		if !datav.IsValid() { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		return badtype("slice", data) | ||||||
|  | 	} | ||||||
|  | 	sliceLen := datav.Len() | ||||||
|  | 	if sliceLen != rv.Len() { | ||||||
|  | 		return e("expected array length %d; got TOML array of length %d", | ||||||
|  | 			rv.Len(), sliceLen) | ||||||
|  | 	} | ||||||
|  | 	return md.unifySliceArray(datav, rv) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error { | ||||||
|  | 	datav := reflect.ValueOf(data) | ||||||
|  | 	if datav.Kind() != reflect.Slice { | ||||||
|  | 		if !datav.IsValid() { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		return badtype("slice", data) | ||||||
|  | 	} | ||||||
|  | 	n := datav.Len() | ||||||
|  | 	if rv.IsNil() || rv.Cap() < n { | ||||||
|  | 		rv.Set(reflect.MakeSlice(rv.Type(), n, n)) | ||||||
|  | 	} | ||||||
|  | 	rv.SetLen(n) | ||||||
|  | 	return md.unifySliceArray(datav, rv) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifySliceArray(data, rv reflect.Value) error { | ||||||
|  | 	sliceLen := data.Len() | ||||||
|  | 	for i := 0; i < sliceLen; i++ { | ||||||
|  | 		v := data.Index(i).Interface() | ||||||
|  | 		sliceval := indirect(rv.Index(i)) | ||||||
|  | 		if err := md.unify(v, sliceval); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error { | ||||||
|  | 	if _, ok := data.(time.Time); ok { | ||||||
|  | 		rv.Set(reflect.ValueOf(data)) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	return badtype("time.Time", data) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error { | ||||||
|  | 	if s, ok := data.(string); ok { | ||||||
|  | 		rv.SetString(s) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	return badtype("string", data) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error { | ||||||
|  | 	if num, ok := data.(float64); ok { | ||||||
|  | 		switch rv.Kind() { | ||||||
|  | 		case reflect.Float32: | ||||||
|  | 			fallthrough | ||||||
|  | 		case reflect.Float64: | ||||||
|  | 			rv.SetFloat(num) | ||||||
|  | 		default: | ||||||
|  | 			panic("bug") | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	return badtype("float", data) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error { | ||||||
|  | 	if num, ok := data.(int64); ok { | ||||||
|  | 		if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 { | ||||||
|  | 			switch rv.Kind() { | ||||||
|  | 			case reflect.Int, reflect.Int64: | ||||||
|  | 				// No bounds checking necessary.
 | ||||||
|  | 			case reflect.Int8: | ||||||
|  | 				if num < math.MinInt8 || num > math.MaxInt8 { | ||||||
|  | 					return e("value %d is out of range for int8", num) | ||||||
|  | 				} | ||||||
|  | 			case reflect.Int16: | ||||||
|  | 				if num < math.MinInt16 || num > math.MaxInt16 { | ||||||
|  | 					return e("value %d is out of range for int16", num) | ||||||
|  | 				} | ||||||
|  | 			case reflect.Int32: | ||||||
|  | 				if num < math.MinInt32 || num > math.MaxInt32 { | ||||||
|  | 					return e("value %d is out of range for int32", num) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			rv.SetInt(num) | ||||||
|  | 		} else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 { | ||||||
|  | 			unum := uint64(num) | ||||||
|  | 			switch rv.Kind() { | ||||||
|  | 			case reflect.Uint, reflect.Uint64: | ||||||
|  | 				// No bounds checking necessary.
 | ||||||
|  | 			case reflect.Uint8: | ||||||
|  | 				if num < 0 || unum > math.MaxUint8 { | ||||||
|  | 					return e("value %d is out of range for uint8", num) | ||||||
|  | 				} | ||||||
|  | 			case reflect.Uint16: | ||||||
|  | 				if num < 0 || unum > math.MaxUint16 { | ||||||
|  | 					return e("value %d is out of range for uint16", num) | ||||||
|  | 				} | ||||||
|  | 			case reflect.Uint32: | ||||||
|  | 				if num < 0 || unum > math.MaxUint32 { | ||||||
|  | 					return e("value %d is out of range for uint32", num) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			rv.SetUint(unum) | ||||||
|  | 		} else { | ||||||
|  | 			panic("unreachable") | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	return badtype("integer", data) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error { | ||||||
|  | 	if b, ok := data.(bool); ok { | ||||||
|  | 		rv.SetBool(b) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	return badtype("boolean", data) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error { | ||||||
|  | 	rv.Set(reflect.ValueOf(data)) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error { | ||||||
|  | 	var s string | ||||||
|  | 	switch sdata := data.(type) { | ||||||
|  | 	case TextMarshaler: | ||||||
|  | 		text, err := sdata.MarshalText() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		s = string(text) | ||||||
|  | 	case fmt.Stringer: | ||||||
|  | 		s = sdata.String() | ||||||
|  | 	case string: | ||||||
|  | 		s = sdata | ||||||
|  | 	case bool: | ||||||
|  | 		s = fmt.Sprintf("%v", sdata) | ||||||
|  | 	case int64: | ||||||
|  | 		s = fmt.Sprintf("%d", sdata) | ||||||
|  | 	case float64: | ||||||
|  | 		s = fmt.Sprintf("%f", sdata) | ||||||
|  | 	default: | ||||||
|  | 		return badtype("primitive (string-like)", data) | ||||||
|  | 	} | ||||||
|  | 	if err := v.UnmarshalText([]byte(s)); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // rvalue returns a reflect.Value of `v`. All pointers are resolved.
 | ||||||
|  | func rvalue(v interface{}) reflect.Value { | ||||||
|  | 	return indirect(reflect.ValueOf(v)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // indirect returns the value pointed to by a pointer.
 | ||||||
|  | // Pointers are followed until the value is not a pointer.
 | ||||||
|  | // New values are allocated for each nil pointer.
 | ||||||
|  | //
 | ||||||
|  | // An exception to this rule is if the value satisfies an interface of
 | ||||||
|  | // interest to us (like encoding.TextUnmarshaler).
 | ||||||
|  | func indirect(v reflect.Value) reflect.Value { | ||||||
|  | 	if v.Kind() != reflect.Ptr { | ||||||
|  | 		if v.CanSet() { | ||||||
|  | 			pv := v.Addr() | ||||||
|  | 			if _, ok := pv.Interface().(TextUnmarshaler); ok { | ||||||
|  | 				return pv | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return v | ||||||
|  | 	} | ||||||
|  | 	if v.IsNil() { | ||||||
|  | 		v.Set(reflect.New(v.Type().Elem())) | ||||||
|  | 	} | ||||||
|  | 	return indirect(reflect.Indirect(v)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isUnifiable(rv reflect.Value) bool { | ||||||
|  | 	if rv.CanSet() { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	if _, ok := rv.Interface().(TextUnmarshaler); ok { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func badtype(expected string, data interface{}) error { | ||||||
|  | 	return e("cannot load TOML value of type %T into a Go %s", data, expected) | ||||||
|  | } | ||||||
|  | @ -0,0 +1,121 @@ | ||||||
|  | package toml | ||||||
|  | 
 | ||||||
|  | import "strings" | ||||||
|  | 
 | ||||||
|  | // MetaData allows access to meta information about TOML data that may not
 | ||||||
|  | // be inferrable via reflection. In particular, whether a key has been defined
 | ||||||
|  | // and the TOML type of a key.
 | ||||||
|  | type MetaData struct { | ||||||
|  | 	mapping map[string]interface{} | ||||||
|  | 	types   map[string]tomlType | ||||||
|  | 	keys    []Key | ||||||
|  | 	decoded map[string]bool | ||||||
|  | 	context Key // Used only during decoding.
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // IsDefined returns true if the key given exists in the TOML data. The key
 | ||||||
|  | // should be specified hierarchially. e.g.,
 | ||||||
|  | //
 | ||||||
|  | //	// access the TOML key 'a.b.c'
 | ||||||
|  | //	IsDefined("a", "b", "c")
 | ||||||
|  | //
 | ||||||
|  | // IsDefined will return false if an empty key given. Keys are case sensitive.
 | ||||||
|  | func (md *MetaData) IsDefined(key ...string) bool { | ||||||
|  | 	if len(key) == 0 { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var hash map[string]interface{} | ||||||
|  | 	var ok bool | ||||||
|  | 	var hashOrVal interface{} = md.mapping | ||||||
|  | 	for _, k := range key { | ||||||
|  | 		if hash, ok = hashOrVal.(map[string]interface{}); !ok { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 		if hashOrVal, ok = hash[k]; !ok { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Type returns a string representation of the type of the key specified.
 | ||||||
|  | //
 | ||||||
|  | // Type will return the empty string if given an empty key or a key that
 | ||||||
|  | // does not exist. Keys are case sensitive.
 | ||||||
|  | func (md *MetaData) Type(key ...string) string { | ||||||
|  | 	fullkey := strings.Join(key, ".") | ||||||
|  | 	if typ, ok := md.types[fullkey]; ok { | ||||||
|  | 		return typ.typeString() | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Key is the type of any TOML key, including key groups. Use (MetaData).Keys
 | ||||||
|  | // to get values of this type.
 | ||||||
|  | type Key []string | ||||||
|  | 
 | ||||||
|  | func (k Key) String() string { | ||||||
|  | 	return strings.Join(k, ".") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (k Key) maybeQuotedAll() string { | ||||||
|  | 	var ss []string | ||||||
|  | 	for i := range k { | ||||||
|  | 		ss = append(ss, k.maybeQuoted(i)) | ||||||
|  | 	} | ||||||
|  | 	return strings.Join(ss, ".") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (k Key) maybeQuoted(i int) string { | ||||||
|  | 	quote := false | ||||||
|  | 	for _, c := range k[i] { | ||||||
|  | 		if !isBareKeyChar(c) { | ||||||
|  | 			quote = true | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if quote { | ||||||
|  | 		return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\"" | ||||||
|  | 	} | ||||||
|  | 	return k[i] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (k Key) add(piece string) Key { | ||||||
|  | 	newKey := make(Key, len(k)+1) | ||||||
|  | 	copy(newKey, k) | ||||||
|  | 	newKey[len(k)] = piece | ||||||
|  | 	return newKey | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Keys returns a slice of every key in the TOML data, including key groups.
 | ||||||
|  | // Each key is itself a slice, where the first element is the top of the
 | ||||||
|  | // hierarchy and the last is the most specific.
 | ||||||
|  | //
 | ||||||
|  | // The list will have the same order as the keys appeared in the TOML data.
 | ||||||
|  | //
 | ||||||
|  | // All keys returned are non-empty.
 | ||||||
|  | func (md *MetaData) Keys() []Key { | ||||||
|  | 	return md.keys | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Undecoded returns all keys that have not been decoded in the order in which
 | ||||||
|  | // they appear in the original TOML document.
 | ||||||
|  | //
 | ||||||
|  | // This includes keys that haven't been decoded because of a Primitive value.
 | ||||||
|  | // Once the Primitive value is decoded, the keys will be considered decoded.
 | ||||||
|  | //
 | ||||||
|  | // Also note that decoding into an empty interface will result in no decoding,
 | ||||||
|  | // and so no keys will be considered decoded.
 | ||||||
|  | //
 | ||||||
|  | // In this sense, the Undecoded keys correspond to keys in the TOML document
 | ||||||
|  | // that do not have a concrete type in your representation.
 | ||||||
|  | func (md *MetaData) Undecoded() []Key { | ||||||
|  | 	undecoded := make([]Key, 0, len(md.keys)) | ||||||
|  | 	for _, key := range md.keys { | ||||||
|  | 		if !md.decoded[key.String()] { | ||||||
|  | 			undecoded = append(undecoded, key) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return undecoded | ||||||
|  | } | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | /* | ||||||
|  | Package toml provides facilities for decoding and encoding TOML configuration | ||||||
|  | files via reflection. There is also support for delaying decoding with | ||||||
|  | the Primitive type, and querying the set of keys in a TOML document with the | ||||||
|  | MetaData type. | ||||||
|  | 
 | ||||||
|  | The specification implemented: https://github.com/toml-lang/toml
 | ||||||
|  | 
 | ||||||
|  | The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify | ||||||
|  | whether a file is a valid TOML document. It can also be used to print the | ||||||
|  | type of each key in a TOML document. | ||||||
|  | 
 | ||||||
|  | Testing | ||||||
|  | 
 | ||||||
|  | There are two important types of tests used for this package. The first is | ||||||
|  | contained inside '*_test.go' files and uses the standard Go unit testing | ||||||
|  | framework. These tests are primarily devoted to holistically testing the | ||||||
|  | decoder and encoder. | ||||||
|  | 
 | ||||||
|  | The second type of testing is used to verify the implementation's adherence | ||||||
|  | to the TOML specification. These tests have been factored into their own | ||||||
|  | project: https://github.com/BurntSushi/toml-test
 | ||||||
|  | 
 | ||||||
|  | The reason the tests are in a separate project is so that they can be used by | ||||||
|  | any implementation of TOML. Namely, it is language agnostic. | ||||||
|  | */ | ||||||
|  | package toml | ||||||
|  | @ -0,0 +1,568 @@ | ||||||
|  | package toml | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"reflect" | ||||||
|  | 	"sort" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type tomlEncodeError struct{ error } | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	errArrayMixedElementTypes = errors.New( | ||||||
|  | 		"toml: cannot encode array with mixed element types") | ||||||
|  | 	errArrayNilElement = errors.New( | ||||||
|  | 		"toml: cannot encode array with nil element") | ||||||
|  | 	errNonString = errors.New( | ||||||
|  | 		"toml: cannot encode a map with non-string key type") | ||||||
|  | 	errAnonNonStruct = errors.New( | ||||||
|  | 		"toml: cannot encode an anonymous field that is not a struct") | ||||||
|  | 	errArrayNoTable = errors.New( | ||||||
|  | 		"toml: TOML array element cannot contain a table") | ||||||
|  | 	errNoKey = errors.New( | ||||||
|  | 		"toml: top-level values must be Go maps or structs") | ||||||
|  | 	errAnything = errors.New("") // used in testing
 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var quotedReplacer = strings.NewReplacer( | ||||||
|  | 	"\t", "\\t", | ||||||
|  | 	"\n", "\\n", | ||||||
|  | 	"\r", "\\r", | ||||||
|  | 	"\"", "\\\"", | ||||||
|  | 	"\\", "\\\\", | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Encoder controls the encoding of Go values to a TOML document to some
 | ||||||
|  | // io.Writer.
 | ||||||
|  | //
 | ||||||
|  | // The indentation level can be controlled with the Indent field.
 | ||||||
|  | type Encoder struct { | ||||||
|  | 	// A single indentation level. By default it is two spaces.
 | ||||||
|  | 	Indent string | ||||||
|  | 
 | ||||||
|  | 	// hasWritten is whether we have written any output to w yet.
 | ||||||
|  | 	hasWritten bool | ||||||
|  | 	w          *bufio.Writer | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // NewEncoder returns a TOML encoder that encodes Go values to the io.Writer
 | ||||||
|  | // given. By default, a single indentation level is 2 spaces.
 | ||||||
|  | func NewEncoder(w io.Writer) *Encoder { | ||||||
|  | 	return &Encoder{ | ||||||
|  | 		w:      bufio.NewWriter(w), | ||||||
|  | 		Indent: "  ", | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Encode writes a TOML representation of the Go value to the underlying
 | ||||||
|  | // io.Writer. If the value given cannot be encoded to a valid TOML document,
 | ||||||
|  | // then an error is returned.
 | ||||||
|  | //
 | ||||||
|  | // The mapping between Go values and TOML values should be precisely the same
 | ||||||
|  | // as for the Decode* functions. Similarly, the TextMarshaler interface is
 | ||||||
|  | // supported by encoding the resulting bytes as strings. (If you want to write
 | ||||||
|  | // arbitrary binary data then you will need to use something like base64 since
 | ||||||
|  | // TOML does not have any binary types.)
 | ||||||
|  | //
 | ||||||
|  | // When encoding TOML hashes (i.e., Go maps or structs), keys without any
 | ||||||
|  | // sub-hashes are encoded first.
 | ||||||
|  | //
 | ||||||
|  | // If a Go map is encoded, then its keys are sorted alphabetically for
 | ||||||
|  | // deterministic output. More control over this behavior may be provided if
 | ||||||
|  | // there is demand for it.
 | ||||||
|  | //
 | ||||||
|  | // Encoding Go values without a corresponding TOML representation---like map
 | ||||||
|  | // types with non-string keys---will cause an error to be returned. Similarly
 | ||||||
|  | // for mixed arrays/slices, arrays/slices with nil elements, embedded
 | ||||||
|  | // non-struct types and nested slices containing maps or structs.
 | ||||||
|  | // (e.g., [][]map[string]string is not allowed but []map[string]string is OK
 | ||||||
|  | // and so is []map[string][]string.)
 | ||||||
|  | func (enc *Encoder) Encode(v interface{}) error { | ||||||
|  | 	rv := eindirect(reflect.ValueOf(v)) | ||||||
|  | 	if err := enc.safeEncode(Key([]string{}), rv); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	return enc.w.Flush() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			if terr, ok := r.(tomlEncodeError); ok { | ||||||
|  | 				err = terr.error | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			panic(r) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	enc.encode(key, rv) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) encode(key Key, rv reflect.Value) { | ||||||
|  | 	// Special case. Time needs to be in ISO8601 format.
 | ||||||
|  | 	// Special case. If we can marshal the type to text, then we used that.
 | ||||||
|  | 	// Basically, this prevents the encoder for handling these types as
 | ||||||
|  | 	// generic structs (or whatever the underlying type of a TextMarshaler is).
 | ||||||
|  | 	switch rv.Interface().(type) { | ||||||
|  | 	case time.Time, TextMarshaler: | ||||||
|  | 		enc.keyEqElement(key, rv) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	k := rv.Kind() | ||||||
|  | 	switch k { | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, | ||||||
|  | 		reflect.Int64, | ||||||
|  | 		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, | ||||||
|  | 		reflect.Uint64, | ||||||
|  | 		reflect.Float32, reflect.Float64, reflect.String, reflect.Bool: | ||||||
|  | 		enc.keyEqElement(key, rv) | ||||||
|  | 	case reflect.Array, reflect.Slice: | ||||||
|  | 		if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) { | ||||||
|  | 			enc.eArrayOfTables(key, rv) | ||||||
|  | 		} else { | ||||||
|  | 			enc.keyEqElement(key, rv) | ||||||
|  | 		} | ||||||
|  | 	case reflect.Interface: | ||||||
|  | 		if rv.IsNil() { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		enc.encode(key, rv.Elem()) | ||||||
|  | 	case reflect.Map: | ||||||
|  | 		if rv.IsNil() { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		enc.eTable(key, rv) | ||||||
|  | 	case reflect.Ptr: | ||||||
|  | 		if rv.IsNil() { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		enc.encode(key, rv.Elem()) | ||||||
|  | 	case reflect.Struct: | ||||||
|  | 		enc.eTable(key, rv) | ||||||
|  | 	default: | ||||||
|  | 		panic(e("unsupported type for key '%s': %s", key, k)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // eElement encodes any value that can be an array element (primitives and
 | ||||||
|  | // arrays).
 | ||||||
|  | func (enc *Encoder) eElement(rv reflect.Value) { | ||||||
|  | 	switch v := rv.Interface().(type) { | ||||||
|  | 	case time.Time: | ||||||
|  | 		// Special case time.Time as a primitive. Has to come before
 | ||||||
|  | 		// TextMarshaler below because time.Time implements
 | ||||||
|  | 		// encoding.TextMarshaler, but we need to always use UTC.
 | ||||||
|  | 		enc.wf(v.UTC().Format("2006-01-02T15:04:05Z")) | ||||||
|  | 		return | ||||||
|  | 	case TextMarshaler: | ||||||
|  | 		// Special case. Use text marshaler if it's available for this value.
 | ||||||
|  | 		if s, err := v.MarshalText(); err != nil { | ||||||
|  | 			encPanic(err) | ||||||
|  | 		} else { | ||||||
|  | 			enc.writeQuoted(string(s)) | ||||||
|  | 		} | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	switch rv.Kind() { | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		enc.wf(strconv.FormatBool(rv.Bool())) | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, | ||||||
|  | 		reflect.Int64: | ||||||
|  | 		enc.wf(strconv.FormatInt(rv.Int(), 10)) | ||||||
|  | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, | ||||||
|  | 		reflect.Uint32, reflect.Uint64: | ||||||
|  | 		enc.wf(strconv.FormatUint(rv.Uint(), 10)) | ||||||
|  | 	case reflect.Float32: | ||||||
|  | 		enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32))) | ||||||
|  | 	case reflect.Float64: | ||||||
|  | 		enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64))) | ||||||
|  | 	case reflect.Array, reflect.Slice: | ||||||
|  | 		enc.eArrayOrSliceElement(rv) | ||||||
|  | 	case reflect.Interface: | ||||||
|  | 		enc.eElement(rv.Elem()) | ||||||
|  | 	case reflect.String: | ||||||
|  | 		enc.writeQuoted(rv.String()) | ||||||
|  | 	default: | ||||||
|  | 		panic(e("unexpected primitive type: %s", rv.Kind())) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // By the TOML spec, all floats must have a decimal with at least one
 | ||||||
|  | // number on either side.
 | ||||||
|  | func floatAddDecimal(fstr string) string { | ||||||
|  | 	if !strings.Contains(fstr, ".") { | ||||||
|  | 		return fstr + ".0" | ||||||
|  | 	} | ||||||
|  | 	return fstr | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) writeQuoted(s string) { | ||||||
|  | 	enc.wf("\"%s\"", quotedReplacer.Replace(s)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) { | ||||||
|  | 	length := rv.Len() | ||||||
|  | 	enc.wf("[") | ||||||
|  | 	for i := 0; i < length; i++ { | ||||||
|  | 		elem := rv.Index(i) | ||||||
|  | 		enc.eElement(elem) | ||||||
|  | 		if i != length-1 { | ||||||
|  | 			enc.wf(", ") | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	enc.wf("]") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) { | ||||||
|  | 	if len(key) == 0 { | ||||||
|  | 		encPanic(errNoKey) | ||||||
|  | 	} | ||||||
|  | 	for i := 0; i < rv.Len(); i++ { | ||||||
|  | 		trv := rv.Index(i) | ||||||
|  | 		if isNil(trv) { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		panicIfInvalidKey(key) | ||||||
|  | 		enc.newline() | ||||||
|  | 		enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll()) | ||||||
|  | 		enc.newline() | ||||||
|  | 		enc.eMapOrStruct(key, trv) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) eTable(key Key, rv reflect.Value) { | ||||||
|  | 	panicIfInvalidKey(key) | ||||||
|  | 	if len(key) == 1 { | ||||||
|  | 		// Output an extra newline between top-level tables.
 | ||||||
|  | 		// (The newline isn't written if nothing else has been written though.)
 | ||||||
|  | 		enc.newline() | ||||||
|  | 	} | ||||||
|  | 	if len(key) > 0 { | ||||||
|  | 		enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll()) | ||||||
|  | 		enc.newline() | ||||||
|  | 	} | ||||||
|  | 	enc.eMapOrStruct(key, rv) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) { | ||||||
|  | 	switch rv := eindirect(rv); rv.Kind() { | ||||||
|  | 	case reflect.Map: | ||||||
|  | 		enc.eMap(key, rv) | ||||||
|  | 	case reflect.Struct: | ||||||
|  | 		enc.eStruct(key, rv) | ||||||
|  | 	default: | ||||||
|  | 		panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) eMap(key Key, rv reflect.Value) { | ||||||
|  | 	rt := rv.Type() | ||||||
|  | 	if rt.Key().Kind() != reflect.String { | ||||||
|  | 		encPanic(errNonString) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Sort keys so that we have deterministic output. And write keys directly
 | ||||||
|  | 	// underneath this key first, before writing sub-structs or sub-maps.
 | ||||||
|  | 	var mapKeysDirect, mapKeysSub []string | ||||||
|  | 	for _, mapKey := range rv.MapKeys() { | ||||||
|  | 		k := mapKey.String() | ||||||
|  | 		if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) { | ||||||
|  | 			mapKeysSub = append(mapKeysSub, k) | ||||||
|  | 		} else { | ||||||
|  | 			mapKeysDirect = append(mapKeysDirect, k) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var writeMapKeys = func(mapKeys []string) { | ||||||
|  | 		sort.Strings(mapKeys) | ||||||
|  | 		for _, mapKey := range mapKeys { | ||||||
|  | 			mrv := rv.MapIndex(reflect.ValueOf(mapKey)) | ||||||
|  | 			if isNil(mrv) { | ||||||
|  | 				// Don't write anything for nil fields.
 | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			enc.encode(key.add(mapKey), mrv) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	writeMapKeys(mapKeysDirect) | ||||||
|  | 	writeMapKeys(mapKeysSub) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) eStruct(key Key, rv reflect.Value) { | ||||||
|  | 	// Write keys for fields directly under this key first, because if we write
 | ||||||
|  | 	// a field that creates a new table, then all keys under it will be in that
 | ||||||
|  | 	// table (not the one we're writing here).
 | ||||||
|  | 	rt := rv.Type() | ||||||
|  | 	var fieldsDirect, fieldsSub [][]int | ||||||
|  | 	var addFields func(rt reflect.Type, rv reflect.Value, start []int) | ||||||
|  | 	addFields = func(rt reflect.Type, rv reflect.Value, start []int) { | ||||||
|  | 		for i := 0; i < rt.NumField(); i++ { | ||||||
|  | 			f := rt.Field(i) | ||||||
|  | 			// skip unexported fields
 | ||||||
|  | 			if f.PkgPath != "" && !f.Anonymous { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			frv := rv.Field(i) | ||||||
|  | 			if f.Anonymous { | ||||||
|  | 				t := f.Type | ||||||
|  | 				switch t.Kind() { | ||||||
|  | 				case reflect.Struct: | ||||||
|  | 					// Treat anonymous struct fields with
 | ||||||
|  | 					// tag names as though they are not
 | ||||||
|  | 					// anonymous, like encoding/json does.
 | ||||||
|  | 					if getOptions(f.Tag).name == "" { | ||||||
|  | 						addFields(t, frv, f.Index) | ||||||
|  | 						continue | ||||||
|  | 					} | ||||||
|  | 				case reflect.Ptr: | ||||||
|  | 					if t.Elem().Kind() == reflect.Struct && | ||||||
|  | 						getOptions(f.Tag).name == "" { | ||||||
|  | 						if !frv.IsNil() { | ||||||
|  | 							addFields(t.Elem(), frv.Elem(), f.Index) | ||||||
|  | 						} | ||||||
|  | 						continue | ||||||
|  | 					} | ||||||
|  | 					// Fall through to the normal field encoding logic below
 | ||||||
|  | 					// for non-struct anonymous fields.
 | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if typeIsHash(tomlTypeOfGo(frv)) { | ||||||
|  | 				fieldsSub = append(fieldsSub, append(start, f.Index...)) | ||||||
|  | 			} else { | ||||||
|  | 				fieldsDirect = append(fieldsDirect, append(start, f.Index...)) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	addFields(rt, rv, nil) | ||||||
|  | 
 | ||||||
|  | 	var writeFields = func(fields [][]int) { | ||||||
|  | 		for _, fieldIndex := range fields { | ||||||
|  | 			sft := rt.FieldByIndex(fieldIndex) | ||||||
|  | 			sf := rv.FieldByIndex(fieldIndex) | ||||||
|  | 			if isNil(sf) { | ||||||
|  | 				// Don't write anything for nil fields.
 | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			opts := getOptions(sft.Tag) | ||||||
|  | 			if opts.skip { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			keyName := sft.Name | ||||||
|  | 			if opts.name != "" { | ||||||
|  | 				keyName = opts.name | ||||||
|  | 			} | ||||||
|  | 			if opts.omitempty && isEmpty(sf) { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			if opts.omitzero && isZero(sf) { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			enc.encode(key.add(keyName), sf) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	writeFields(fieldsDirect) | ||||||
|  | 	writeFields(fieldsSub) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // tomlTypeName returns the TOML type name of the Go value's type. It is
 | ||||||
|  | // used to determine whether the types of array elements are mixed (which is
 | ||||||
|  | // forbidden). If the Go value is nil, then it is illegal for it to be an array
 | ||||||
|  | // element, and valueIsNil is returned as true.
 | ||||||
|  | 
 | ||||||
|  | // Returns the TOML type of a Go value. The type may be `nil`, which means
 | ||||||
|  | // no concrete TOML type could be found.
 | ||||||
|  | func tomlTypeOfGo(rv reflect.Value) tomlType { | ||||||
|  | 	if isNil(rv) || !rv.IsValid() { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	switch rv.Kind() { | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		return tomlBool | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, | ||||||
|  | 		reflect.Int64, | ||||||
|  | 		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, | ||||||
|  | 		reflect.Uint64: | ||||||
|  | 		return tomlInteger | ||||||
|  | 	case reflect.Float32, reflect.Float64: | ||||||
|  | 		return tomlFloat | ||||||
|  | 	case reflect.Array, reflect.Slice: | ||||||
|  | 		if typeEqual(tomlHash, tomlArrayType(rv)) { | ||||||
|  | 			return tomlArrayHash | ||||||
|  | 		} | ||||||
|  | 		return tomlArray | ||||||
|  | 	case reflect.Ptr, reflect.Interface: | ||||||
|  | 		return tomlTypeOfGo(rv.Elem()) | ||||||
|  | 	case reflect.String: | ||||||
|  | 		return tomlString | ||||||
|  | 	case reflect.Map: | ||||||
|  | 		return tomlHash | ||||||
|  | 	case reflect.Struct: | ||||||
|  | 		switch rv.Interface().(type) { | ||||||
|  | 		case time.Time: | ||||||
|  | 			return tomlDatetime | ||||||
|  | 		case TextMarshaler: | ||||||
|  | 			return tomlString | ||||||
|  | 		default: | ||||||
|  | 			return tomlHash | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		panic("unexpected reflect.Kind: " + rv.Kind().String()) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // tomlArrayType returns the element type of a TOML array. The type returned
 | ||||||
|  | // may be nil if it cannot be determined (e.g., a nil slice or a zero length
 | ||||||
|  | // slize). This function may also panic if it finds a type that cannot be
 | ||||||
|  | // expressed in TOML (such as nil elements, heterogeneous arrays or directly
 | ||||||
|  | // nested arrays of tables).
 | ||||||
|  | func tomlArrayType(rv reflect.Value) tomlType { | ||||||
|  | 	if isNil(rv) || !rv.IsValid() || rv.Len() == 0 { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	firstType := tomlTypeOfGo(rv.Index(0)) | ||||||
|  | 	if firstType == nil { | ||||||
|  | 		encPanic(errArrayNilElement) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	rvlen := rv.Len() | ||||||
|  | 	for i := 1; i < rvlen; i++ { | ||||||
|  | 		elem := rv.Index(i) | ||||||
|  | 		switch elemType := tomlTypeOfGo(elem); { | ||||||
|  | 		case elemType == nil: | ||||||
|  | 			encPanic(errArrayNilElement) | ||||||
|  | 		case !typeEqual(firstType, elemType): | ||||||
|  | 			encPanic(errArrayMixedElementTypes) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// If we have a nested array, then we must make sure that the nested
 | ||||||
|  | 	// array contains ONLY primitives.
 | ||||||
|  | 	// This checks arbitrarily nested arrays.
 | ||||||
|  | 	if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) { | ||||||
|  | 		nest := tomlArrayType(eindirect(rv.Index(0))) | ||||||
|  | 		if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) { | ||||||
|  | 			encPanic(errArrayNoTable) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return firstType | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type tagOptions struct { | ||||||
|  | 	skip      bool // "-"
 | ||||||
|  | 	name      string | ||||||
|  | 	omitempty bool | ||||||
|  | 	omitzero  bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func getOptions(tag reflect.StructTag) tagOptions { | ||||||
|  | 	t := tag.Get("toml") | ||||||
|  | 	if t == "-" { | ||||||
|  | 		return tagOptions{skip: true} | ||||||
|  | 	} | ||||||
|  | 	var opts tagOptions | ||||||
|  | 	parts := strings.Split(t, ",") | ||||||
|  | 	opts.name = parts[0] | ||||||
|  | 	for _, s := range parts[1:] { | ||||||
|  | 		switch s { | ||||||
|  | 		case "omitempty": | ||||||
|  | 			opts.omitempty = true | ||||||
|  | 		case "omitzero": | ||||||
|  | 			opts.omitzero = true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return opts | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isZero(rv reflect.Value) bool { | ||||||
|  | 	switch rv.Kind() { | ||||||
|  | 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: | ||||||
|  | 		return rv.Int() == 0 | ||||||
|  | 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: | ||||||
|  | 		return rv.Uint() == 0 | ||||||
|  | 	case reflect.Float32, reflect.Float64: | ||||||
|  | 		return rv.Float() == 0.0 | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isEmpty(rv reflect.Value) bool { | ||||||
|  | 	switch rv.Kind() { | ||||||
|  | 	case reflect.Array, reflect.Slice, reflect.Map, reflect.String: | ||||||
|  | 		return rv.Len() == 0 | ||||||
|  | 	case reflect.Bool: | ||||||
|  | 		return !rv.Bool() | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) newline() { | ||||||
|  | 	if enc.hasWritten { | ||||||
|  | 		enc.wf("\n") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) keyEqElement(key Key, val reflect.Value) { | ||||||
|  | 	if len(key) == 0 { | ||||||
|  | 		encPanic(errNoKey) | ||||||
|  | 	} | ||||||
|  | 	panicIfInvalidKey(key) | ||||||
|  | 	enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1)) | ||||||
|  | 	enc.eElement(val) | ||||||
|  | 	enc.newline() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) wf(format string, v ...interface{}) { | ||||||
|  | 	if _, err := fmt.Fprintf(enc.w, format, v...); err != nil { | ||||||
|  | 		encPanic(err) | ||||||
|  | 	} | ||||||
|  | 	enc.hasWritten = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (enc *Encoder) indentStr(key Key) string { | ||||||
|  | 	return strings.Repeat(enc.Indent, len(key)-1) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func encPanic(err error) { | ||||||
|  | 	panic(tomlEncodeError{err}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func eindirect(v reflect.Value) reflect.Value { | ||||||
|  | 	switch v.Kind() { | ||||||
|  | 	case reflect.Ptr, reflect.Interface: | ||||||
|  | 		return eindirect(v.Elem()) | ||||||
|  | 	default: | ||||||
|  | 		return v | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isNil(rv reflect.Value) bool { | ||||||
|  | 	switch rv.Kind() { | ||||||
|  | 	case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: | ||||||
|  | 		return rv.IsNil() | ||||||
|  | 	default: | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func panicIfInvalidKey(key Key) { | ||||||
|  | 	for _, k := range key { | ||||||
|  | 		if len(k) == 0 { | ||||||
|  | 			encPanic(e("Key '%s' is not a valid table name. Key names "+ | ||||||
|  | 				"cannot be empty.", key.maybeQuotedAll())) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isValidKeyName(s string) bool { | ||||||
|  | 	return len(s) != 0 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | // +build go1.2
 | ||||||
|  | 
 | ||||||
|  | package toml | ||||||
|  | 
 | ||||||
|  | // In order to support Go 1.1, we define our own TextMarshaler and
 | ||||||
|  | // TextUnmarshaler types. For Go 1.2+, we just alias them with the
 | ||||||
|  | // standard library interfaces.
 | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
 | ||||||
|  | // so that Go 1.1 can be supported.
 | ||||||
|  | type TextMarshaler encoding.TextMarshaler | ||||||
|  | 
 | ||||||
|  | // TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
 | ||||||
|  | // here so that Go 1.1 can be supported.
 | ||||||
|  | type TextUnmarshaler encoding.TextUnmarshaler | ||||||
|  | @ -0,0 +1,18 @@ | ||||||
|  | // +build !go1.2
 | ||||||
|  | 
 | ||||||
|  | package toml | ||||||
|  | 
 | ||||||
|  | // These interfaces were introduced in Go 1.2, so we add them manually when
 | ||||||
|  | // compiling for Go 1.1.
 | ||||||
|  | 
 | ||||||
|  | // TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
 | ||||||
|  | // so that Go 1.1 can be supported.
 | ||||||
|  | type TextMarshaler interface { | ||||||
|  | 	MarshalText() (text []byte, err error) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
 | ||||||
|  | // here so that Go 1.1 can be supported.
 | ||||||
|  | type TextUnmarshaler interface { | ||||||
|  | 	UnmarshalText(text []byte) error | ||||||
|  | } | ||||||
|  | @ -0,0 +1,953 @@ | ||||||
|  | package toml | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | 	"unicode" | ||||||
|  | 	"unicode/utf8" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type itemType int | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	itemError itemType = iota | ||||||
|  | 	itemNIL            // used in the parser to indicate no type
 | ||||||
|  | 	itemEOF | ||||||
|  | 	itemText | ||||||
|  | 	itemString | ||||||
|  | 	itemRawString | ||||||
|  | 	itemMultilineString | ||||||
|  | 	itemRawMultilineString | ||||||
|  | 	itemBool | ||||||
|  | 	itemInteger | ||||||
|  | 	itemFloat | ||||||
|  | 	itemDatetime | ||||||
|  | 	itemArray // the start of an array
 | ||||||
|  | 	itemArrayEnd | ||||||
|  | 	itemTableStart | ||||||
|  | 	itemTableEnd | ||||||
|  | 	itemArrayTableStart | ||||||
|  | 	itemArrayTableEnd | ||||||
|  | 	itemKeyStart | ||||||
|  | 	itemCommentStart | ||||||
|  | 	itemInlineTableStart | ||||||
|  | 	itemInlineTableEnd | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	eof              = 0 | ||||||
|  | 	comma            = ',' | ||||||
|  | 	tableStart       = '[' | ||||||
|  | 	tableEnd         = ']' | ||||||
|  | 	arrayTableStart  = '[' | ||||||
|  | 	arrayTableEnd    = ']' | ||||||
|  | 	tableSep         = '.' | ||||||
|  | 	keySep           = '=' | ||||||
|  | 	arrayStart       = '[' | ||||||
|  | 	arrayEnd         = ']' | ||||||
|  | 	commentStart     = '#' | ||||||
|  | 	stringStart      = '"' | ||||||
|  | 	stringEnd        = '"' | ||||||
|  | 	rawStringStart   = '\'' | ||||||
|  | 	rawStringEnd     = '\'' | ||||||
|  | 	inlineTableStart = '{' | ||||||
|  | 	inlineTableEnd   = '}' | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type stateFn func(lx *lexer) stateFn | ||||||
|  | 
 | ||||||
|  | type lexer struct { | ||||||
|  | 	input string | ||||||
|  | 	start int | ||||||
|  | 	pos   int | ||||||
|  | 	line  int | ||||||
|  | 	state stateFn | ||||||
|  | 	items chan item | ||||||
|  | 
 | ||||||
|  | 	// Allow for backing up up to three runes.
 | ||||||
|  | 	// This is necessary because TOML contains 3-rune tokens (""" and ''').
 | ||||||
|  | 	prevWidths [3]int | ||||||
|  | 	nprev      int // how many of prevWidths are in use
 | ||||||
|  | 	// If we emit an eof, we can still back up, but it is not OK to call
 | ||||||
|  | 	// next again.
 | ||||||
|  | 	atEOF bool | ||||||
|  | 
 | ||||||
|  | 	// A stack of state functions used to maintain context.
 | ||||||
|  | 	// The idea is to reuse parts of the state machine in various places.
 | ||||||
|  | 	// For example, values can appear at the top level or within arbitrarily
 | ||||||
|  | 	// nested arrays. The last state on the stack is used after a value has
 | ||||||
|  | 	// been lexed. Similarly for comments.
 | ||||||
|  | 	stack []stateFn | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type item struct { | ||||||
|  | 	typ  itemType | ||||||
|  | 	val  string | ||||||
|  | 	line int | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lx *lexer) nextItem() item { | ||||||
|  | 	for { | ||||||
|  | 		select { | ||||||
|  | 		case item := <-lx.items: | ||||||
|  | 			return item | ||||||
|  | 		default: | ||||||
|  | 			lx.state = lx.state(lx) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func lex(input string) *lexer { | ||||||
|  | 	lx := &lexer{ | ||||||
|  | 		input: input, | ||||||
|  | 		state: lexTop, | ||||||
|  | 		line:  1, | ||||||
|  | 		items: make(chan item, 10), | ||||||
|  | 		stack: make([]stateFn, 0, 10), | ||||||
|  | 	} | ||||||
|  | 	return lx | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lx *lexer) push(state stateFn) { | ||||||
|  | 	lx.stack = append(lx.stack, state) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lx *lexer) pop() stateFn { | ||||||
|  | 	if len(lx.stack) == 0 { | ||||||
|  | 		return lx.errorf("BUG in lexer: no states to pop") | ||||||
|  | 	} | ||||||
|  | 	last := lx.stack[len(lx.stack)-1] | ||||||
|  | 	lx.stack = lx.stack[0 : len(lx.stack)-1] | ||||||
|  | 	return last | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lx *lexer) current() string { | ||||||
|  | 	return lx.input[lx.start:lx.pos] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lx *lexer) emit(typ itemType) { | ||||||
|  | 	lx.items <- item{typ, lx.current(), lx.line} | ||||||
|  | 	lx.start = lx.pos | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lx *lexer) emitTrim(typ itemType) { | ||||||
|  | 	lx.items <- item{typ, strings.TrimSpace(lx.current()), lx.line} | ||||||
|  | 	lx.start = lx.pos | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (lx *lexer) next() (r rune) { | ||||||
|  | 	if lx.atEOF { | ||||||
|  | 		panic("next called after EOF") | ||||||
|  | 	} | ||||||
|  | 	if lx.pos >= len(lx.input) { | ||||||
|  | 		lx.atEOF = true | ||||||
|  | 		return eof | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if lx.input[lx.pos] == '\n' { | ||||||
|  | 		lx.line++ | ||||||
|  | 	} | ||||||
|  | 	lx.prevWidths[2] = lx.prevWidths[1] | ||||||
|  | 	lx.prevWidths[1] = lx.prevWidths[0] | ||||||
|  | 	if lx.nprev < 3 { | ||||||
|  | 		lx.nprev++ | ||||||
|  | 	} | ||||||
|  | 	r, w := utf8.DecodeRuneInString(lx.input[lx.pos:]) | ||||||
|  | 	lx.prevWidths[0] = w | ||||||
|  | 	lx.pos += w | ||||||
|  | 	return r | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ignore skips over the pending input before this point.
 | ||||||
|  | func (lx *lexer) ignore() { | ||||||
|  | 	lx.start = lx.pos | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // backup steps back one rune. Can be called only twice between calls to next.
 | ||||||
|  | func (lx *lexer) backup() { | ||||||
|  | 	if lx.atEOF { | ||||||
|  | 		lx.atEOF = false | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	if lx.nprev < 1 { | ||||||
|  | 		panic("backed up too far") | ||||||
|  | 	} | ||||||
|  | 	w := lx.prevWidths[0] | ||||||
|  | 	lx.prevWidths[0] = lx.prevWidths[1] | ||||||
|  | 	lx.prevWidths[1] = lx.prevWidths[2] | ||||||
|  | 	lx.nprev-- | ||||||
|  | 	lx.pos -= w | ||||||
|  | 	if lx.pos < len(lx.input) && lx.input[lx.pos] == '\n' { | ||||||
|  | 		lx.line-- | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // accept consumes the next rune if it's equal to `valid`.
 | ||||||
|  | func (lx *lexer) accept(valid rune) bool { | ||||||
|  | 	if lx.next() == valid { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	lx.backup() | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // peek returns but does not consume the next rune in the input.
 | ||||||
|  | func (lx *lexer) peek() rune { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	lx.backup() | ||||||
|  | 	return r | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // skip ignores all input that matches the given predicate.
 | ||||||
|  | func (lx *lexer) skip(pred func(rune) bool) { | ||||||
|  | 	for { | ||||||
|  | 		r := lx.next() | ||||||
|  | 		if pred(r) { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		lx.backup() | ||||||
|  | 		lx.ignore() | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // errorf stops all lexing by emitting an error and returning `nil`.
 | ||||||
|  | // Note that any value that is a character is escaped if it's a special
 | ||||||
|  | // character (newlines, tabs, etc.).
 | ||||||
|  | func (lx *lexer) errorf(format string, values ...interface{}) stateFn { | ||||||
|  | 	lx.items <- item{ | ||||||
|  | 		itemError, | ||||||
|  | 		fmt.Sprintf(format, values...), | ||||||
|  | 		lx.line, | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexTop consumes elements at the top level of TOML data.
 | ||||||
|  | func lexTop(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	if isWhitespace(r) || isNL(r) { | ||||||
|  | 		return lexSkip(lx, lexTop) | ||||||
|  | 	} | ||||||
|  | 	switch r { | ||||||
|  | 	case commentStart: | ||||||
|  | 		lx.push(lexTop) | ||||||
|  | 		return lexCommentStart | ||||||
|  | 	case tableStart: | ||||||
|  | 		return lexTableStart | ||||||
|  | 	case eof: | ||||||
|  | 		if lx.pos > lx.start { | ||||||
|  | 			return lx.errorf("unexpected EOF") | ||||||
|  | 		} | ||||||
|  | 		lx.emit(itemEOF) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// At this point, the only valid item can be a key, so we back up
 | ||||||
|  | 	// and let the key lexer do the rest.
 | ||||||
|  | 	lx.backup() | ||||||
|  | 	lx.push(lexTopEnd) | ||||||
|  | 	return lexKeyStart | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexTopEnd is entered whenever a top-level item has been consumed. (A value
 | ||||||
|  | // or a table.) It must see only whitespace, and will turn back to lexTop
 | ||||||
|  | // upon a newline. If it sees EOF, it will quit the lexer successfully.
 | ||||||
|  | func lexTopEnd(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	switch { | ||||||
|  | 	case r == commentStart: | ||||||
|  | 		// a comment will read to a newline for us.
 | ||||||
|  | 		lx.push(lexTop) | ||||||
|  | 		return lexCommentStart | ||||||
|  | 	case isWhitespace(r): | ||||||
|  | 		return lexTopEnd | ||||||
|  | 	case isNL(r): | ||||||
|  | 		lx.ignore() | ||||||
|  | 		return lexTop | ||||||
|  | 	case r == eof: | ||||||
|  | 		lx.emit(itemEOF) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	return lx.errorf("expected a top-level item to end with a newline, "+ | ||||||
|  | 		"comment, or EOF, but got %q instead", r) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexTable lexes the beginning of a table. Namely, it makes sure that
 | ||||||
|  | // it starts with a character other than '.' and ']'.
 | ||||||
|  | // It assumes that '[' has already been consumed.
 | ||||||
|  | // It also handles the case that this is an item in an array of tables.
 | ||||||
|  | // e.g., '[[name]]'.
 | ||||||
|  | func lexTableStart(lx *lexer) stateFn { | ||||||
|  | 	if lx.peek() == arrayTableStart { | ||||||
|  | 		lx.next() | ||||||
|  | 		lx.emit(itemArrayTableStart) | ||||||
|  | 		lx.push(lexArrayTableEnd) | ||||||
|  | 	} else { | ||||||
|  | 		lx.emit(itemTableStart) | ||||||
|  | 		lx.push(lexTableEnd) | ||||||
|  | 	} | ||||||
|  | 	return lexTableNameStart | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func lexTableEnd(lx *lexer) stateFn { | ||||||
|  | 	lx.emit(itemTableEnd) | ||||||
|  | 	return lexTopEnd | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func lexArrayTableEnd(lx *lexer) stateFn { | ||||||
|  | 	if r := lx.next(); r != arrayTableEnd { | ||||||
|  | 		return lx.errorf("expected end of table array name delimiter %q, "+ | ||||||
|  | 			"but got %q instead", arrayTableEnd, r) | ||||||
|  | 	} | ||||||
|  | 	lx.emit(itemArrayTableEnd) | ||||||
|  | 	return lexTopEnd | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func lexTableNameStart(lx *lexer) stateFn { | ||||||
|  | 	lx.skip(isWhitespace) | ||||||
|  | 	switch r := lx.peek(); { | ||||||
|  | 	case r == tableEnd || r == eof: | ||||||
|  | 		return lx.errorf("unexpected end of table name " + | ||||||
|  | 			"(table names cannot be empty)") | ||||||
|  | 	case r == tableSep: | ||||||
|  | 		return lx.errorf("unexpected table separator " + | ||||||
|  | 			"(table names cannot be empty)") | ||||||
|  | 	case r == stringStart || r == rawStringStart: | ||||||
|  | 		lx.ignore() | ||||||
|  | 		lx.push(lexTableNameEnd) | ||||||
|  | 		return lexValue // reuse string lexing
 | ||||||
|  | 	default: | ||||||
|  | 		return lexBareTableName | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexBareTableName lexes the name of a table. It assumes that at least one
 | ||||||
|  | // valid character for the table has already been read.
 | ||||||
|  | func lexBareTableName(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	if isBareKeyChar(r) { | ||||||
|  | 		return lexBareTableName | ||||||
|  | 	} | ||||||
|  | 	lx.backup() | ||||||
|  | 	lx.emit(itemText) | ||||||
|  | 	return lexTableNameEnd | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexTableNameEnd reads the end of a piece of a table name, optionally
 | ||||||
|  | // consuming whitespace.
 | ||||||
|  | func lexTableNameEnd(lx *lexer) stateFn { | ||||||
|  | 	lx.skip(isWhitespace) | ||||||
|  | 	switch r := lx.next(); { | ||||||
|  | 	case isWhitespace(r): | ||||||
|  | 		return lexTableNameEnd | ||||||
|  | 	case r == tableSep: | ||||||
|  | 		lx.ignore() | ||||||
|  | 		return lexTableNameStart | ||||||
|  | 	case r == tableEnd: | ||||||
|  | 		return lx.pop() | ||||||
|  | 	default: | ||||||
|  | 		return lx.errorf("expected '.' or ']' to end table name, "+ | ||||||
|  | 			"but got %q instead", r) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexKeyStart consumes a key name up until the first non-whitespace character.
 | ||||||
|  | // lexKeyStart will ignore whitespace.
 | ||||||
|  | func lexKeyStart(lx *lexer) stateFn { | ||||||
|  | 	r := lx.peek() | ||||||
|  | 	switch { | ||||||
|  | 	case r == keySep: | ||||||
|  | 		return lx.errorf("unexpected key separator %q", keySep) | ||||||
|  | 	case isWhitespace(r) || isNL(r): | ||||||
|  | 		lx.next() | ||||||
|  | 		return lexSkip(lx, lexKeyStart) | ||||||
|  | 	case r == stringStart || r == rawStringStart: | ||||||
|  | 		lx.ignore() | ||||||
|  | 		lx.emit(itemKeyStart) | ||||||
|  | 		lx.push(lexKeyEnd) | ||||||
|  | 		return lexValue // reuse string lexing
 | ||||||
|  | 	default: | ||||||
|  | 		lx.ignore() | ||||||
|  | 		lx.emit(itemKeyStart) | ||||||
|  | 		return lexBareKey | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexBareKey consumes the text of a bare key. Assumes that the first character
 | ||||||
|  | // (which is not whitespace) has not yet been consumed.
 | ||||||
|  | func lexBareKey(lx *lexer) stateFn { | ||||||
|  | 	switch r := lx.next(); { | ||||||
|  | 	case isBareKeyChar(r): | ||||||
|  | 		return lexBareKey | ||||||
|  | 	case isWhitespace(r): | ||||||
|  | 		lx.backup() | ||||||
|  | 		lx.emit(itemText) | ||||||
|  | 		return lexKeyEnd | ||||||
|  | 	case r == keySep: | ||||||
|  | 		lx.backup() | ||||||
|  | 		lx.emit(itemText) | ||||||
|  | 		return lexKeyEnd | ||||||
|  | 	default: | ||||||
|  | 		return lx.errorf("bare keys cannot contain %q", r) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexKeyEnd consumes the end of a key and trims whitespace (up to the key
 | ||||||
|  | // separator).
 | ||||||
|  | func lexKeyEnd(lx *lexer) stateFn { | ||||||
|  | 	switch r := lx.next(); { | ||||||
|  | 	case r == keySep: | ||||||
|  | 		return lexSkip(lx, lexValue) | ||||||
|  | 	case isWhitespace(r): | ||||||
|  | 		return lexSkip(lx, lexKeyEnd) | ||||||
|  | 	default: | ||||||
|  | 		return lx.errorf("expected key separator %q, but got %q instead", | ||||||
|  | 			keySep, r) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexValue starts the consumption of a value anywhere a value is expected.
 | ||||||
|  | // lexValue will ignore whitespace.
 | ||||||
|  | // After a value is lexed, the last state on the next is popped and returned.
 | ||||||
|  | func lexValue(lx *lexer) stateFn { | ||||||
|  | 	// We allow whitespace to precede a value, but NOT newlines.
 | ||||||
|  | 	// In array syntax, the array states are responsible for ignoring newlines.
 | ||||||
|  | 	r := lx.next() | ||||||
|  | 	switch { | ||||||
|  | 	case isWhitespace(r): | ||||||
|  | 		return lexSkip(lx, lexValue) | ||||||
|  | 	case isDigit(r): | ||||||
|  | 		lx.backup() // avoid an extra state and use the same as above
 | ||||||
|  | 		return lexNumberOrDateStart | ||||||
|  | 	} | ||||||
|  | 	switch r { | ||||||
|  | 	case arrayStart: | ||||||
|  | 		lx.ignore() | ||||||
|  | 		lx.emit(itemArray) | ||||||
|  | 		return lexArrayValue | ||||||
|  | 	case inlineTableStart: | ||||||
|  | 		lx.ignore() | ||||||
|  | 		lx.emit(itemInlineTableStart) | ||||||
|  | 		return lexInlineTableValue | ||||||
|  | 	case stringStart: | ||||||
|  | 		if lx.accept(stringStart) { | ||||||
|  | 			if lx.accept(stringStart) { | ||||||
|  | 				lx.ignore() // Ignore """
 | ||||||
|  | 				return lexMultilineString | ||||||
|  | 			} | ||||||
|  | 			lx.backup() | ||||||
|  | 		} | ||||||
|  | 		lx.ignore() // ignore the '"'
 | ||||||
|  | 		return lexString | ||||||
|  | 	case rawStringStart: | ||||||
|  | 		if lx.accept(rawStringStart) { | ||||||
|  | 			if lx.accept(rawStringStart) { | ||||||
|  | 				lx.ignore() // Ignore """
 | ||||||
|  | 				return lexMultilineRawString | ||||||
|  | 			} | ||||||
|  | 			lx.backup() | ||||||
|  | 		} | ||||||
|  | 		lx.ignore() // ignore the "'"
 | ||||||
|  | 		return lexRawString | ||||||
|  | 	case '+', '-': | ||||||
|  | 		return lexNumberStart | ||||||
|  | 	case '.': // special error case, be kind to users
 | ||||||
|  | 		return lx.errorf("floats must start with a digit, not '.'") | ||||||
|  | 	} | ||||||
|  | 	if unicode.IsLetter(r) { | ||||||
|  | 		// Be permissive here; lexBool will give a nice error if the
 | ||||||
|  | 		// user wrote something like
 | ||||||
|  | 		//   x = foo
 | ||||||
|  | 		// (i.e. not 'true' or 'false' but is something else word-like.)
 | ||||||
|  | 		lx.backup() | ||||||
|  | 		return lexBool | ||||||
|  | 	} | ||||||
|  | 	return lx.errorf("expected value but found %q instead", r) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexArrayValue consumes one value in an array. It assumes that '[' or ','
 | ||||||
|  | // have already been consumed. All whitespace and newlines are ignored.
 | ||||||
|  | func lexArrayValue(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	switch { | ||||||
|  | 	case isWhitespace(r) || isNL(r): | ||||||
|  | 		return lexSkip(lx, lexArrayValue) | ||||||
|  | 	case r == commentStart: | ||||||
|  | 		lx.push(lexArrayValue) | ||||||
|  | 		return lexCommentStart | ||||||
|  | 	case r == comma: | ||||||
|  | 		return lx.errorf("unexpected comma") | ||||||
|  | 	case r == arrayEnd: | ||||||
|  | 		// NOTE(caleb): The spec isn't clear about whether you can have
 | ||||||
|  | 		// a trailing comma or not, so we'll allow it.
 | ||||||
|  | 		return lexArrayEnd | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lx.backup() | ||||||
|  | 	lx.push(lexArrayValueEnd) | ||||||
|  | 	return lexValue | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexArrayValueEnd consumes everything between the end of an array value and
 | ||||||
|  | // the next value (or the end of the array): it ignores whitespace and newlines
 | ||||||
|  | // and expects either a ',' or a ']'.
 | ||||||
|  | func lexArrayValueEnd(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	switch { | ||||||
|  | 	case isWhitespace(r) || isNL(r): | ||||||
|  | 		return lexSkip(lx, lexArrayValueEnd) | ||||||
|  | 	case r == commentStart: | ||||||
|  | 		lx.push(lexArrayValueEnd) | ||||||
|  | 		return lexCommentStart | ||||||
|  | 	case r == comma: | ||||||
|  | 		lx.ignore() | ||||||
|  | 		return lexArrayValue // move on to the next value
 | ||||||
|  | 	case r == arrayEnd: | ||||||
|  | 		return lexArrayEnd | ||||||
|  | 	} | ||||||
|  | 	return lx.errorf( | ||||||
|  | 		"expected a comma or array terminator %q, but got %q instead", | ||||||
|  | 		arrayEnd, r, | ||||||
|  | 	) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexArrayEnd finishes the lexing of an array.
 | ||||||
|  | // It assumes that a ']' has just been consumed.
 | ||||||
|  | func lexArrayEnd(lx *lexer) stateFn { | ||||||
|  | 	lx.ignore() | ||||||
|  | 	lx.emit(itemArrayEnd) | ||||||
|  | 	return lx.pop() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexInlineTableValue consumes one key/value pair in an inline table.
 | ||||||
|  | // It assumes that '{' or ',' have already been consumed. Whitespace is ignored.
 | ||||||
|  | func lexInlineTableValue(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	switch { | ||||||
|  | 	case isWhitespace(r): | ||||||
|  | 		return lexSkip(lx, lexInlineTableValue) | ||||||
|  | 	case isNL(r): | ||||||
|  | 		return lx.errorf("newlines not allowed within inline tables") | ||||||
|  | 	case r == commentStart: | ||||||
|  | 		lx.push(lexInlineTableValue) | ||||||
|  | 		return lexCommentStart | ||||||
|  | 	case r == comma: | ||||||
|  | 		return lx.errorf("unexpected comma") | ||||||
|  | 	case r == inlineTableEnd: | ||||||
|  | 		return lexInlineTableEnd | ||||||
|  | 	} | ||||||
|  | 	lx.backup() | ||||||
|  | 	lx.push(lexInlineTableValueEnd) | ||||||
|  | 	return lexKeyStart | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexInlineTableValueEnd consumes everything between the end of an inline table
 | ||||||
|  | // key/value pair and the next pair (or the end of the table):
 | ||||||
|  | // it ignores whitespace and expects either a ',' or a '}'.
 | ||||||
|  | func lexInlineTableValueEnd(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	switch { | ||||||
|  | 	case isWhitespace(r): | ||||||
|  | 		return lexSkip(lx, lexInlineTableValueEnd) | ||||||
|  | 	case isNL(r): | ||||||
|  | 		return lx.errorf("newlines not allowed within inline tables") | ||||||
|  | 	case r == commentStart: | ||||||
|  | 		lx.push(lexInlineTableValueEnd) | ||||||
|  | 		return lexCommentStart | ||||||
|  | 	case r == comma: | ||||||
|  | 		lx.ignore() | ||||||
|  | 		return lexInlineTableValue | ||||||
|  | 	case r == inlineTableEnd: | ||||||
|  | 		return lexInlineTableEnd | ||||||
|  | 	} | ||||||
|  | 	return lx.errorf("expected a comma or an inline table terminator %q, "+ | ||||||
|  | 		"but got %q instead", inlineTableEnd, r) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexInlineTableEnd finishes the lexing of an inline table.
 | ||||||
|  | // It assumes that a '}' has just been consumed.
 | ||||||
|  | func lexInlineTableEnd(lx *lexer) stateFn { | ||||||
|  | 	lx.ignore() | ||||||
|  | 	lx.emit(itemInlineTableEnd) | ||||||
|  | 	return lx.pop() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexString consumes the inner contents of a string. It assumes that the
 | ||||||
|  | // beginning '"' has already been consumed and ignored.
 | ||||||
|  | func lexString(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	switch { | ||||||
|  | 	case r == eof: | ||||||
|  | 		return lx.errorf("unexpected EOF") | ||||||
|  | 	case isNL(r): | ||||||
|  | 		return lx.errorf("strings cannot contain newlines") | ||||||
|  | 	case r == '\\': | ||||||
|  | 		lx.push(lexString) | ||||||
|  | 		return lexStringEscape | ||||||
|  | 	case r == stringEnd: | ||||||
|  | 		lx.backup() | ||||||
|  | 		lx.emit(itemString) | ||||||
|  | 		lx.next() | ||||||
|  | 		lx.ignore() | ||||||
|  | 		return lx.pop() | ||||||
|  | 	} | ||||||
|  | 	return lexString | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexMultilineString consumes the inner contents of a string. It assumes that
 | ||||||
|  | // the beginning '"""' has already been consumed and ignored.
 | ||||||
|  | func lexMultilineString(lx *lexer) stateFn { | ||||||
|  | 	switch lx.next() { | ||||||
|  | 	case eof: | ||||||
|  | 		return lx.errorf("unexpected EOF") | ||||||
|  | 	case '\\': | ||||||
|  | 		return lexMultilineStringEscape | ||||||
|  | 	case stringEnd: | ||||||
|  | 		if lx.accept(stringEnd) { | ||||||
|  | 			if lx.accept(stringEnd) { | ||||||
|  | 				lx.backup() | ||||||
|  | 				lx.backup() | ||||||
|  | 				lx.backup() | ||||||
|  | 				lx.emit(itemMultilineString) | ||||||
|  | 				lx.next() | ||||||
|  | 				lx.next() | ||||||
|  | 				lx.next() | ||||||
|  | 				lx.ignore() | ||||||
|  | 				return lx.pop() | ||||||
|  | 			} | ||||||
|  | 			lx.backup() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return lexMultilineString | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexRawString consumes a raw string. Nothing can be escaped in such a string.
 | ||||||
|  | // It assumes that the beginning "'" has already been consumed and ignored.
 | ||||||
|  | func lexRawString(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	switch { | ||||||
|  | 	case r == eof: | ||||||
|  | 		return lx.errorf("unexpected EOF") | ||||||
|  | 	case isNL(r): | ||||||
|  | 		return lx.errorf("strings cannot contain newlines") | ||||||
|  | 	case r == rawStringEnd: | ||||||
|  | 		lx.backup() | ||||||
|  | 		lx.emit(itemRawString) | ||||||
|  | 		lx.next() | ||||||
|  | 		lx.ignore() | ||||||
|  | 		return lx.pop() | ||||||
|  | 	} | ||||||
|  | 	return lexRawString | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexMultilineRawString consumes a raw string. Nothing can be escaped in such
 | ||||||
|  | // a string. It assumes that the beginning "'''" has already been consumed and
 | ||||||
|  | // ignored.
 | ||||||
|  | func lexMultilineRawString(lx *lexer) stateFn { | ||||||
|  | 	switch lx.next() { | ||||||
|  | 	case eof: | ||||||
|  | 		return lx.errorf("unexpected EOF") | ||||||
|  | 	case rawStringEnd: | ||||||
|  | 		if lx.accept(rawStringEnd) { | ||||||
|  | 			if lx.accept(rawStringEnd) { | ||||||
|  | 				lx.backup() | ||||||
|  | 				lx.backup() | ||||||
|  | 				lx.backup() | ||||||
|  | 				lx.emit(itemRawMultilineString) | ||||||
|  | 				lx.next() | ||||||
|  | 				lx.next() | ||||||
|  | 				lx.next() | ||||||
|  | 				lx.ignore() | ||||||
|  | 				return lx.pop() | ||||||
|  | 			} | ||||||
|  | 			lx.backup() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return lexMultilineRawString | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexMultilineStringEscape consumes an escaped character. It assumes that the
 | ||||||
|  | // preceding '\\' has already been consumed.
 | ||||||
|  | func lexMultilineStringEscape(lx *lexer) stateFn { | ||||||
|  | 	// Handle the special case first:
 | ||||||
|  | 	if isNL(lx.next()) { | ||||||
|  | 		return lexMultilineString | ||||||
|  | 	} | ||||||
|  | 	lx.backup() | ||||||
|  | 	lx.push(lexMultilineString) | ||||||
|  | 	return lexStringEscape(lx) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func lexStringEscape(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	switch r { | ||||||
|  | 	case 'b': | ||||||
|  | 		fallthrough | ||||||
|  | 	case 't': | ||||||
|  | 		fallthrough | ||||||
|  | 	case 'n': | ||||||
|  | 		fallthrough | ||||||
|  | 	case 'f': | ||||||
|  | 		fallthrough | ||||||
|  | 	case 'r': | ||||||
|  | 		fallthrough | ||||||
|  | 	case '"': | ||||||
|  | 		fallthrough | ||||||
|  | 	case '\\': | ||||||
|  | 		return lx.pop() | ||||||
|  | 	case 'u': | ||||||
|  | 		return lexShortUnicodeEscape | ||||||
|  | 	case 'U': | ||||||
|  | 		return lexLongUnicodeEscape | ||||||
|  | 	} | ||||||
|  | 	return lx.errorf("invalid escape character %q; only the following "+ | ||||||
|  | 		"escape characters are allowed: "+ | ||||||
|  | 		`\b, \t, \n, \f, \r, \", \\, \uXXXX, and \UXXXXXXXX`, r) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func lexShortUnicodeEscape(lx *lexer) stateFn { | ||||||
|  | 	var r rune | ||||||
|  | 	for i := 0; i < 4; i++ { | ||||||
|  | 		r = lx.next() | ||||||
|  | 		if !isHexadecimal(r) { | ||||||
|  | 			return lx.errorf(`expected four hexadecimal digits after '\u', `+ | ||||||
|  | 				"but got %q instead", lx.current()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return lx.pop() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func lexLongUnicodeEscape(lx *lexer) stateFn { | ||||||
|  | 	var r rune | ||||||
|  | 	for i := 0; i < 8; i++ { | ||||||
|  | 		r = lx.next() | ||||||
|  | 		if !isHexadecimal(r) { | ||||||
|  | 			return lx.errorf(`expected eight hexadecimal digits after '\U', `+ | ||||||
|  | 				"but got %q instead", lx.current()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return lx.pop() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexNumberOrDateStart consumes either an integer, a float, or datetime.
 | ||||||
|  | func lexNumberOrDateStart(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	if isDigit(r) { | ||||||
|  | 		return lexNumberOrDate | ||||||
|  | 	} | ||||||
|  | 	switch r { | ||||||
|  | 	case '_': | ||||||
|  | 		return lexNumber | ||||||
|  | 	case 'e', 'E': | ||||||
|  | 		return lexFloat | ||||||
|  | 	case '.': | ||||||
|  | 		return lx.errorf("floats must start with a digit, not '.'") | ||||||
|  | 	} | ||||||
|  | 	return lx.errorf("expected a digit but got %q", r) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexNumberOrDate consumes either an integer, float or datetime.
 | ||||||
|  | func lexNumberOrDate(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	if isDigit(r) { | ||||||
|  | 		return lexNumberOrDate | ||||||
|  | 	} | ||||||
|  | 	switch r { | ||||||
|  | 	case '-': | ||||||
|  | 		return lexDatetime | ||||||
|  | 	case '_': | ||||||
|  | 		return lexNumber | ||||||
|  | 	case '.', 'e', 'E': | ||||||
|  | 		return lexFloat | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lx.backup() | ||||||
|  | 	lx.emit(itemInteger) | ||||||
|  | 	return lx.pop() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexDatetime consumes a Datetime, to a first approximation.
 | ||||||
|  | // The parser validates that it matches one of the accepted formats.
 | ||||||
|  | func lexDatetime(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	if isDigit(r) { | ||||||
|  | 		return lexDatetime | ||||||
|  | 	} | ||||||
|  | 	switch r { | ||||||
|  | 	case '-', 'T', ':', '.', 'Z', '+': | ||||||
|  | 		return lexDatetime | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lx.backup() | ||||||
|  | 	lx.emit(itemDatetime) | ||||||
|  | 	return lx.pop() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexNumberStart consumes either an integer or a float. It assumes that a sign
 | ||||||
|  | // has already been read, but that *no* digits have been consumed.
 | ||||||
|  | // lexNumberStart will move to the appropriate integer or float states.
 | ||||||
|  | func lexNumberStart(lx *lexer) stateFn { | ||||||
|  | 	// We MUST see a digit. Even floats have to start with a digit.
 | ||||||
|  | 	r := lx.next() | ||||||
|  | 	if !isDigit(r) { | ||||||
|  | 		if r == '.' { | ||||||
|  | 			return lx.errorf("floats must start with a digit, not '.'") | ||||||
|  | 		} | ||||||
|  | 		return lx.errorf("expected a digit but got %q", r) | ||||||
|  | 	} | ||||||
|  | 	return lexNumber | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexNumber consumes an integer or a float after seeing the first digit.
 | ||||||
|  | func lexNumber(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	if isDigit(r) { | ||||||
|  | 		return lexNumber | ||||||
|  | 	} | ||||||
|  | 	switch r { | ||||||
|  | 	case '_': | ||||||
|  | 		return lexNumber | ||||||
|  | 	case '.', 'e', 'E': | ||||||
|  | 		return lexFloat | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lx.backup() | ||||||
|  | 	lx.emit(itemInteger) | ||||||
|  | 	return lx.pop() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexFloat consumes the elements of a float. It allows any sequence of
 | ||||||
|  | // float-like characters, so floats emitted by the lexer are only a first
 | ||||||
|  | // approximation and must be validated by the parser.
 | ||||||
|  | func lexFloat(lx *lexer) stateFn { | ||||||
|  | 	r := lx.next() | ||||||
|  | 	if isDigit(r) { | ||||||
|  | 		return lexFloat | ||||||
|  | 	} | ||||||
|  | 	switch r { | ||||||
|  | 	case '_', '.', '-', '+', 'e', 'E': | ||||||
|  | 		return lexFloat | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lx.backup() | ||||||
|  | 	lx.emit(itemFloat) | ||||||
|  | 	return lx.pop() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexBool consumes a bool string: 'true' or 'false.
 | ||||||
|  | func lexBool(lx *lexer) stateFn { | ||||||
|  | 	var rs []rune | ||||||
|  | 	for { | ||||||
|  | 		r := lx.next() | ||||||
|  | 		if !unicode.IsLetter(r) { | ||||||
|  | 			lx.backup() | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		rs = append(rs, r) | ||||||
|  | 	} | ||||||
|  | 	s := string(rs) | ||||||
|  | 	switch s { | ||||||
|  | 	case "true", "false": | ||||||
|  | 		lx.emit(itemBool) | ||||||
|  | 		return lx.pop() | ||||||
|  | 	} | ||||||
|  | 	return lx.errorf("expected value but found %q instead", s) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexCommentStart begins the lexing of a comment. It will emit
 | ||||||
|  | // itemCommentStart and consume no characters, passing control to lexComment.
 | ||||||
|  | func lexCommentStart(lx *lexer) stateFn { | ||||||
|  | 	lx.ignore() | ||||||
|  | 	lx.emit(itemCommentStart) | ||||||
|  | 	return lexComment | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexComment lexes an entire comment. It assumes that '#' has been consumed.
 | ||||||
|  | // It will consume *up to* the first newline character, and pass control
 | ||||||
|  | // back to the last state on the stack.
 | ||||||
|  | func lexComment(lx *lexer) stateFn { | ||||||
|  | 	r := lx.peek() | ||||||
|  | 	if isNL(r) || r == eof { | ||||||
|  | 		lx.emit(itemText) | ||||||
|  | 		return lx.pop() | ||||||
|  | 	} | ||||||
|  | 	lx.next() | ||||||
|  | 	return lexComment | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // lexSkip ignores all slurped input and moves on to the next state.
 | ||||||
|  | func lexSkip(lx *lexer, nextState stateFn) stateFn { | ||||||
|  | 	return func(lx *lexer) stateFn { | ||||||
|  | 		lx.ignore() | ||||||
|  | 		return nextState | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // isWhitespace returns true if `r` is a whitespace character according
 | ||||||
|  | // to the spec.
 | ||||||
|  | func isWhitespace(r rune) bool { | ||||||
|  | 	return r == '\t' || r == ' ' | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isNL(r rune) bool { | ||||||
|  | 	return r == '\n' || r == '\r' | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isDigit(r rune) bool { | ||||||
|  | 	return r >= '0' && r <= '9' | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isHexadecimal(r rune) bool { | ||||||
|  | 	return (r >= '0' && r <= '9') || | ||||||
|  | 		(r >= 'a' && r <= 'f') || | ||||||
|  | 		(r >= 'A' && r <= 'F') | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isBareKeyChar(r rune) bool { | ||||||
|  | 	return (r >= 'A' && r <= 'Z') || | ||||||
|  | 		(r >= 'a' && r <= 'z') || | ||||||
|  | 		(r >= '0' && r <= '9') || | ||||||
|  | 		r == '_' || | ||||||
|  | 		r == '-' | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (itype itemType) String() string { | ||||||
|  | 	switch itype { | ||||||
|  | 	case itemError: | ||||||
|  | 		return "Error" | ||||||
|  | 	case itemNIL: | ||||||
|  | 		return "NIL" | ||||||
|  | 	case itemEOF: | ||||||
|  | 		return "EOF" | ||||||
|  | 	case itemText: | ||||||
|  | 		return "Text" | ||||||
|  | 	case itemString, itemRawString, itemMultilineString, itemRawMultilineString: | ||||||
|  | 		return "String" | ||||||
|  | 	case itemBool: | ||||||
|  | 		return "Bool" | ||||||
|  | 	case itemInteger: | ||||||
|  | 		return "Integer" | ||||||
|  | 	case itemFloat: | ||||||
|  | 		return "Float" | ||||||
|  | 	case itemDatetime: | ||||||
|  | 		return "DateTime" | ||||||
|  | 	case itemTableStart: | ||||||
|  | 		return "TableStart" | ||||||
|  | 	case itemTableEnd: | ||||||
|  | 		return "TableEnd" | ||||||
|  | 	case itemKeyStart: | ||||||
|  | 		return "KeyStart" | ||||||
|  | 	case itemArray: | ||||||
|  | 		return "Array" | ||||||
|  | 	case itemArrayEnd: | ||||||
|  | 		return "ArrayEnd" | ||||||
|  | 	case itemCommentStart: | ||||||
|  | 		return "CommentStart" | ||||||
|  | 	} | ||||||
|  | 	panic(fmt.Sprintf("BUG: Unknown type '%d'.", int(itype))) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (item item) String() string { | ||||||
|  | 	return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val) | ||||||
|  | } | ||||||
|  | @ -0,0 +1,592 @@ | ||||||
|  | package toml | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | 	"unicode" | ||||||
|  | 	"unicode/utf8" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type parser struct { | ||||||
|  | 	mapping map[string]interface{} | ||||||
|  | 	types   map[string]tomlType | ||||||
|  | 	lx      *lexer | ||||||
|  | 
 | ||||||
|  | 	// A list of keys in the order that they appear in the TOML data.
 | ||||||
|  | 	ordered []Key | ||||||
|  | 
 | ||||||
|  | 	// the full key for the current hash in scope
 | ||||||
|  | 	context Key | ||||||
|  | 
 | ||||||
|  | 	// the base key name for everything except hashes
 | ||||||
|  | 	currentKey string | ||||||
|  | 
 | ||||||
|  | 	// rough approximation of line number
 | ||||||
|  | 	approxLine int | ||||||
|  | 
 | ||||||
|  | 	// A map of 'key.group.names' to whether they were created implicitly.
 | ||||||
|  | 	implicits map[string]bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type parseError string | ||||||
|  | 
 | ||||||
|  | func (pe parseError) Error() string { | ||||||
|  | 	return string(pe) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parse(data string) (p *parser, err error) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if r := recover(); r != nil { | ||||||
|  | 			var ok bool | ||||||
|  | 			if err, ok = r.(parseError); ok { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			panic(r) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 
 | ||||||
|  | 	p = &parser{ | ||||||
|  | 		mapping:   make(map[string]interface{}), | ||||||
|  | 		types:     make(map[string]tomlType), | ||||||
|  | 		lx:        lex(data), | ||||||
|  | 		ordered:   make([]Key, 0), | ||||||
|  | 		implicits: make(map[string]bool), | ||||||
|  | 	} | ||||||
|  | 	for { | ||||||
|  | 		item := p.next() | ||||||
|  | 		if item.typ == itemEOF { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		p.topLevel(item) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return p, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) panicf(format string, v ...interface{}) { | ||||||
|  | 	msg := fmt.Sprintf("Near line %d (last key parsed '%s'): %s", | ||||||
|  | 		p.approxLine, p.current(), fmt.Sprintf(format, v...)) | ||||||
|  | 	panic(parseError(msg)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) next() item { | ||||||
|  | 	it := p.lx.nextItem() | ||||||
|  | 	if it.typ == itemError { | ||||||
|  | 		p.panicf("%s", it.val) | ||||||
|  | 	} | ||||||
|  | 	return it | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) bug(format string, v ...interface{}) { | ||||||
|  | 	panic(fmt.Sprintf("BUG: "+format+"\n\n", v...)) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) expect(typ itemType) item { | ||||||
|  | 	it := p.next() | ||||||
|  | 	p.assertEqual(typ, it.typ) | ||||||
|  | 	return it | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) assertEqual(expected, got itemType) { | ||||||
|  | 	if expected != got { | ||||||
|  | 		p.bug("Expected '%s' but got '%s'.", expected, got) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) topLevel(item item) { | ||||||
|  | 	switch item.typ { | ||||||
|  | 	case itemCommentStart: | ||||||
|  | 		p.approxLine = item.line | ||||||
|  | 		p.expect(itemText) | ||||||
|  | 	case itemTableStart: | ||||||
|  | 		kg := p.next() | ||||||
|  | 		p.approxLine = kg.line | ||||||
|  | 
 | ||||||
|  | 		var key Key | ||||||
|  | 		for ; kg.typ != itemTableEnd && kg.typ != itemEOF; kg = p.next() { | ||||||
|  | 			key = append(key, p.keyString(kg)) | ||||||
|  | 		} | ||||||
|  | 		p.assertEqual(itemTableEnd, kg.typ) | ||||||
|  | 
 | ||||||
|  | 		p.establishContext(key, false) | ||||||
|  | 		p.setType("", tomlHash) | ||||||
|  | 		p.ordered = append(p.ordered, key) | ||||||
|  | 	case itemArrayTableStart: | ||||||
|  | 		kg := p.next() | ||||||
|  | 		p.approxLine = kg.line | ||||||
|  | 
 | ||||||
|  | 		var key Key | ||||||
|  | 		for ; kg.typ != itemArrayTableEnd && kg.typ != itemEOF; kg = p.next() { | ||||||
|  | 			key = append(key, p.keyString(kg)) | ||||||
|  | 		} | ||||||
|  | 		p.assertEqual(itemArrayTableEnd, kg.typ) | ||||||
|  | 
 | ||||||
|  | 		p.establishContext(key, true) | ||||||
|  | 		p.setType("", tomlArrayHash) | ||||||
|  | 		p.ordered = append(p.ordered, key) | ||||||
|  | 	case itemKeyStart: | ||||||
|  | 		kname := p.next() | ||||||
|  | 		p.approxLine = kname.line | ||||||
|  | 		p.currentKey = p.keyString(kname) | ||||||
|  | 
 | ||||||
|  | 		val, typ := p.value(p.next()) | ||||||
|  | 		p.setValue(p.currentKey, val) | ||||||
|  | 		p.setType(p.currentKey, typ) | ||||||
|  | 		p.ordered = append(p.ordered, p.context.add(p.currentKey)) | ||||||
|  | 		p.currentKey = "" | ||||||
|  | 	default: | ||||||
|  | 		p.bug("Unexpected type at top level: %s", item.typ) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Gets a string for a key (or part of a key in a table name).
 | ||||||
|  | func (p *parser) keyString(it item) string { | ||||||
|  | 	switch it.typ { | ||||||
|  | 	case itemText: | ||||||
|  | 		return it.val | ||||||
|  | 	case itemString, itemMultilineString, | ||||||
|  | 		itemRawString, itemRawMultilineString: | ||||||
|  | 		s, _ := p.value(it) | ||||||
|  | 		return s.(string) | ||||||
|  | 	default: | ||||||
|  | 		p.bug("Unexpected key type: %s", it.typ) | ||||||
|  | 		panic("unreachable") | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // value translates an expected value from the lexer into a Go value wrapped
 | ||||||
|  | // as an empty interface.
 | ||||||
|  | func (p *parser) value(it item) (interface{}, tomlType) { | ||||||
|  | 	switch it.typ { | ||||||
|  | 	case itemString: | ||||||
|  | 		return p.replaceEscapes(it.val), p.typeOfPrimitive(it) | ||||||
|  | 	case itemMultilineString: | ||||||
|  | 		trimmed := stripFirstNewline(stripEscapedWhitespace(it.val)) | ||||||
|  | 		return p.replaceEscapes(trimmed), p.typeOfPrimitive(it) | ||||||
|  | 	case itemRawString: | ||||||
|  | 		return it.val, p.typeOfPrimitive(it) | ||||||
|  | 	case itemRawMultilineString: | ||||||
|  | 		return stripFirstNewline(it.val), p.typeOfPrimitive(it) | ||||||
|  | 	case itemBool: | ||||||
|  | 		switch it.val { | ||||||
|  | 		case "true": | ||||||
|  | 			return true, p.typeOfPrimitive(it) | ||||||
|  | 		case "false": | ||||||
|  | 			return false, p.typeOfPrimitive(it) | ||||||
|  | 		} | ||||||
|  | 		p.bug("Expected boolean value, but got '%s'.", it.val) | ||||||
|  | 	case itemInteger: | ||||||
|  | 		if !numUnderscoresOK(it.val) { | ||||||
|  | 			p.panicf("Invalid integer %q: underscores must be surrounded by digits", | ||||||
|  | 				it.val) | ||||||
|  | 		} | ||||||
|  | 		val := strings.Replace(it.val, "_", "", -1) | ||||||
|  | 		num, err := strconv.ParseInt(val, 10, 64) | ||||||
|  | 		if err != nil { | ||||||
|  | 			// Distinguish integer values. Normally, it'd be a bug if the lexer
 | ||||||
|  | 			// provides an invalid integer, but it's possible that the number is
 | ||||||
|  | 			// out of range of valid values (which the lexer cannot determine).
 | ||||||
|  | 			// So mark the former as a bug but the latter as a legitimate user
 | ||||||
|  | 			// error.
 | ||||||
|  | 			if e, ok := err.(*strconv.NumError); ok && | ||||||
|  | 				e.Err == strconv.ErrRange { | ||||||
|  | 
 | ||||||
|  | 				p.panicf("Integer '%s' is out of the range of 64-bit "+ | ||||||
|  | 					"signed integers.", it.val) | ||||||
|  | 			} else { | ||||||
|  | 				p.bug("Expected integer value, but got '%s'.", it.val) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return num, p.typeOfPrimitive(it) | ||||||
|  | 	case itemFloat: | ||||||
|  | 		parts := strings.FieldsFunc(it.val, func(r rune) bool { | ||||||
|  | 			switch r { | ||||||
|  | 			case '.', 'e', 'E': | ||||||
|  | 				return true | ||||||
|  | 			} | ||||||
|  | 			return false | ||||||
|  | 		}) | ||||||
|  | 		for _, part := range parts { | ||||||
|  | 			if !numUnderscoresOK(part) { | ||||||
|  | 				p.panicf("Invalid float %q: underscores must be "+ | ||||||
|  | 					"surrounded by digits", it.val) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if !numPeriodsOK(it.val) { | ||||||
|  | 			// As a special case, numbers like '123.' or '1.e2',
 | ||||||
|  | 			// which are valid as far as Go/strconv are concerned,
 | ||||||
|  | 			// must be rejected because TOML says that a fractional
 | ||||||
|  | 			// part consists of '.' followed by 1+ digits.
 | ||||||
|  | 			p.panicf("Invalid float %q: '.' must be followed "+ | ||||||
|  | 				"by one or more digits", it.val) | ||||||
|  | 		} | ||||||
|  | 		val := strings.Replace(it.val, "_", "", -1) | ||||||
|  | 		num, err := strconv.ParseFloat(val, 64) | ||||||
|  | 		if err != nil { | ||||||
|  | 			if e, ok := err.(*strconv.NumError); ok && | ||||||
|  | 				e.Err == strconv.ErrRange { | ||||||
|  | 
 | ||||||
|  | 				p.panicf("Float '%s' is out of the range of 64-bit "+ | ||||||
|  | 					"IEEE-754 floating-point numbers.", it.val) | ||||||
|  | 			} else { | ||||||
|  | 				p.panicf("Invalid float value: %q", it.val) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return num, p.typeOfPrimitive(it) | ||||||
|  | 	case itemDatetime: | ||||||
|  | 		var t time.Time | ||||||
|  | 		var ok bool | ||||||
|  | 		var err error | ||||||
|  | 		for _, format := range []string{ | ||||||
|  | 			"2006-01-02T15:04:05Z07:00", | ||||||
|  | 			"2006-01-02T15:04:05", | ||||||
|  | 			"2006-01-02", | ||||||
|  | 		} { | ||||||
|  | 			t, err = time.ParseInLocation(format, it.val, time.Local) | ||||||
|  | 			if err == nil { | ||||||
|  | 				ok = true | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if !ok { | ||||||
|  | 			p.panicf("Invalid TOML Datetime: %q.", it.val) | ||||||
|  | 		} | ||||||
|  | 		return t, p.typeOfPrimitive(it) | ||||||
|  | 	case itemArray: | ||||||
|  | 		array := make([]interface{}, 0) | ||||||
|  | 		types := make([]tomlType, 0) | ||||||
|  | 
 | ||||||
|  | 		for it = p.next(); it.typ != itemArrayEnd; it = p.next() { | ||||||
|  | 			if it.typ == itemCommentStart { | ||||||
|  | 				p.expect(itemText) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			val, typ := p.value(it) | ||||||
|  | 			array = append(array, val) | ||||||
|  | 			types = append(types, typ) | ||||||
|  | 		} | ||||||
|  | 		return array, p.typeOfArray(types) | ||||||
|  | 	case itemInlineTableStart: | ||||||
|  | 		var ( | ||||||
|  | 			hash         = make(map[string]interface{}) | ||||||
|  | 			outerContext = p.context | ||||||
|  | 			outerKey     = p.currentKey | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		p.context = append(p.context, p.currentKey) | ||||||
|  | 		p.currentKey = "" | ||||||
|  | 		for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() { | ||||||
|  | 			if it.typ != itemKeyStart { | ||||||
|  | 				p.bug("Expected key start but instead found %q, around line %d", | ||||||
|  | 					it.val, p.approxLine) | ||||||
|  | 			} | ||||||
|  | 			if it.typ == itemCommentStart { | ||||||
|  | 				p.expect(itemText) | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			// retrieve key
 | ||||||
|  | 			k := p.next() | ||||||
|  | 			p.approxLine = k.line | ||||||
|  | 			kname := p.keyString(k) | ||||||
|  | 
 | ||||||
|  | 			// retrieve value
 | ||||||
|  | 			p.currentKey = kname | ||||||
|  | 			val, typ := p.value(p.next()) | ||||||
|  | 			// make sure we keep metadata up to date
 | ||||||
|  | 			p.setType(kname, typ) | ||||||
|  | 			p.ordered = append(p.ordered, p.context.add(p.currentKey)) | ||||||
|  | 			hash[kname] = val | ||||||
|  | 		} | ||||||
|  | 		p.context = outerContext | ||||||
|  | 		p.currentKey = outerKey | ||||||
|  | 		return hash, tomlHash | ||||||
|  | 	} | ||||||
|  | 	p.bug("Unexpected value type: %s", it.typ) | ||||||
|  | 	panic("unreachable") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // numUnderscoresOK checks whether each underscore in s is surrounded by
 | ||||||
|  | // characters that are not underscores.
 | ||||||
|  | func numUnderscoresOK(s string) bool { | ||||||
|  | 	accept := false | ||||||
|  | 	for _, r := range s { | ||||||
|  | 		if r == '_' { | ||||||
|  | 			if !accept { | ||||||
|  | 				return false | ||||||
|  | 			} | ||||||
|  | 			accept = false | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		accept = true | ||||||
|  | 	} | ||||||
|  | 	return accept | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // numPeriodsOK checks whether every period in s is followed by a digit.
 | ||||||
|  | func numPeriodsOK(s string) bool { | ||||||
|  | 	period := false | ||||||
|  | 	for _, r := range s { | ||||||
|  | 		if period && !isDigit(r) { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 		period = r == '.' | ||||||
|  | 	} | ||||||
|  | 	return !period | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // establishContext sets the current context of the parser,
 | ||||||
|  | // where the context is either a hash or an array of hashes. Which one is
 | ||||||
|  | // set depends on the value of the `array` parameter.
 | ||||||
|  | //
 | ||||||
|  | // Establishing the context also makes sure that the key isn't a duplicate, and
 | ||||||
|  | // will create implicit hashes automatically.
 | ||||||
|  | func (p *parser) establishContext(key Key, array bool) { | ||||||
|  | 	var ok bool | ||||||
|  | 
 | ||||||
|  | 	// Always start at the top level and drill down for our context.
 | ||||||
|  | 	hashContext := p.mapping | ||||||
|  | 	keyContext := make(Key, 0) | ||||||
|  | 
 | ||||||
|  | 	// We only need implicit hashes for key[0:-1]
 | ||||||
|  | 	for _, k := range key[0 : len(key)-1] { | ||||||
|  | 		_, ok = hashContext[k] | ||||||
|  | 		keyContext = append(keyContext, k) | ||||||
|  | 
 | ||||||
|  | 		// No key? Make an implicit hash and move on.
 | ||||||
|  | 		if !ok { | ||||||
|  | 			p.addImplicit(keyContext) | ||||||
|  | 			hashContext[k] = make(map[string]interface{}) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// If the hash context is actually an array of tables, then set
 | ||||||
|  | 		// the hash context to the last element in that array.
 | ||||||
|  | 		//
 | ||||||
|  | 		// Otherwise, it better be a table, since this MUST be a key group (by
 | ||||||
|  | 		// virtue of it not being the last element in a key).
 | ||||||
|  | 		switch t := hashContext[k].(type) { | ||||||
|  | 		case []map[string]interface{}: | ||||||
|  | 			hashContext = t[len(t)-1] | ||||||
|  | 		case map[string]interface{}: | ||||||
|  | 			hashContext = t | ||||||
|  | 		default: | ||||||
|  | 			p.panicf("Key '%s' was already created as a hash.", keyContext) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	p.context = keyContext | ||||||
|  | 	if array { | ||||||
|  | 		// If this is the first element for this array, then allocate a new
 | ||||||
|  | 		// list of tables for it.
 | ||||||
|  | 		k := key[len(key)-1] | ||||||
|  | 		if _, ok := hashContext[k]; !ok { | ||||||
|  | 			hashContext[k] = make([]map[string]interface{}, 0, 5) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Add a new table. But make sure the key hasn't already been used
 | ||||||
|  | 		// for something else.
 | ||||||
|  | 		if hash, ok := hashContext[k].([]map[string]interface{}); ok { | ||||||
|  | 			hashContext[k] = append(hash, make(map[string]interface{})) | ||||||
|  | 		} else { | ||||||
|  | 			p.panicf("Key '%s' was already created and cannot be used as "+ | ||||||
|  | 				"an array.", keyContext) | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		p.setValue(key[len(key)-1], make(map[string]interface{})) | ||||||
|  | 	} | ||||||
|  | 	p.context = append(p.context, key[len(key)-1]) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // setValue sets the given key to the given value in the current context.
 | ||||||
|  | // It will make sure that the key hasn't already been defined, account for
 | ||||||
|  | // implicit key groups.
 | ||||||
|  | func (p *parser) setValue(key string, value interface{}) { | ||||||
|  | 	var tmpHash interface{} | ||||||
|  | 	var ok bool | ||||||
|  | 
 | ||||||
|  | 	hash := p.mapping | ||||||
|  | 	keyContext := make(Key, 0) | ||||||
|  | 	for _, k := range p.context { | ||||||
|  | 		keyContext = append(keyContext, k) | ||||||
|  | 		if tmpHash, ok = hash[k]; !ok { | ||||||
|  | 			p.bug("Context for key '%s' has not been established.", keyContext) | ||||||
|  | 		} | ||||||
|  | 		switch t := tmpHash.(type) { | ||||||
|  | 		case []map[string]interface{}: | ||||||
|  | 			// The context is a table of hashes. Pick the most recent table
 | ||||||
|  | 			// defined as the current hash.
 | ||||||
|  | 			hash = t[len(t)-1] | ||||||
|  | 		case map[string]interface{}: | ||||||
|  | 			hash = t | ||||||
|  | 		default: | ||||||
|  | 			p.bug("Expected hash to have type 'map[string]interface{}', but "+ | ||||||
|  | 				"it has '%T' instead.", tmpHash) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	keyContext = append(keyContext, key) | ||||||
|  | 
 | ||||||
|  | 	if _, ok := hash[key]; ok { | ||||||
|  | 		// Typically, if the given key has already been set, then we have
 | ||||||
|  | 		// to raise an error since duplicate keys are disallowed. However,
 | ||||||
|  | 		// it's possible that a key was previously defined implicitly. In this
 | ||||||
|  | 		// case, it is allowed to be redefined concretely. (See the
 | ||||||
|  | 		// `tests/valid/implicit-and-explicit-after.toml` test in `toml-test`.)
 | ||||||
|  | 		//
 | ||||||
|  | 		// But we have to make sure to stop marking it as an implicit. (So that
 | ||||||
|  | 		// another redefinition provokes an error.)
 | ||||||
|  | 		//
 | ||||||
|  | 		// Note that since it has already been defined (as a hash), we don't
 | ||||||
|  | 		// want to overwrite it. So our business is done.
 | ||||||
|  | 		if p.isImplicit(keyContext) { | ||||||
|  | 			p.removeImplicit(keyContext) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Otherwise, we have a concrete key trying to override a previous
 | ||||||
|  | 		// key, which is *always* wrong.
 | ||||||
|  | 		p.panicf("Key '%s' has already been defined.", keyContext) | ||||||
|  | 	} | ||||||
|  | 	hash[key] = value | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // setType sets the type of a particular value at a given key.
 | ||||||
|  | // It should be called immediately AFTER setValue.
 | ||||||
|  | //
 | ||||||
|  | // Note that if `key` is empty, then the type given will be applied to the
 | ||||||
|  | // current context (which is either a table or an array of tables).
 | ||||||
|  | func (p *parser) setType(key string, typ tomlType) { | ||||||
|  | 	keyContext := make(Key, 0, len(p.context)+1) | ||||||
|  | 	for _, k := range p.context { | ||||||
|  | 		keyContext = append(keyContext, k) | ||||||
|  | 	} | ||||||
|  | 	if len(key) > 0 { // allow type setting for hashes
 | ||||||
|  | 		keyContext = append(keyContext, key) | ||||||
|  | 	} | ||||||
|  | 	p.types[keyContext.String()] = typ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // addImplicit sets the given Key as having been created implicitly.
 | ||||||
|  | func (p *parser) addImplicit(key Key) { | ||||||
|  | 	p.implicits[key.String()] = true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // removeImplicit stops tagging the given key as having been implicitly
 | ||||||
|  | // created.
 | ||||||
|  | func (p *parser) removeImplicit(key Key) { | ||||||
|  | 	p.implicits[key.String()] = false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // isImplicit returns true if the key group pointed to by the key was created
 | ||||||
|  | // implicitly.
 | ||||||
|  | func (p *parser) isImplicit(key Key) bool { | ||||||
|  | 	return p.implicits[key.String()] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // current returns the full key name of the current context.
 | ||||||
|  | func (p *parser) current() string { | ||||||
|  | 	if len(p.currentKey) == 0 { | ||||||
|  | 		return p.context.String() | ||||||
|  | 	} | ||||||
|  | 	if len(p.context) == 0 { | ||||||
|  | 		return p.currentKey | ||||||
|  | 	} | ||||||
|  | 	return fmt.Sprintf("%s.%s", p.context, p.currentKey) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func stripFirstNewline(s string) string { | ||||||
|  | 	if len(s) == 0 || s[0] != '\n' { | ||||||
|  | 		return s | ||||||
|  | 	} | ||||||
|  | 	return s[1:] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func stripEscapedWhitespace(s string) string { | ||||||
|  | 	esc := strings.Split(s, "\\\n") | ||||||
|  | 	if len(esc) > 1 { | ||||||
|  | 		for i := 1; i < len(esc); i++ { | ||||||
|  | 			esc[i] = strings.TrimLeftFunc(esc[i], unicode.IsSpace) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return strings.Join(esc, "") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) replaceEscapes(str string) string { | ||||||
|  | 	var replaced []rune | ||||||
|  | 	s := []byte(str) | ||||||
|  | 	r := 0 | ||||||
|  | 	for r < len(s) { | ||||||
|  | 		if s[r] != '\\' { | ||||||
|  | 			c, size := utf8.DecodeRune(s[r:]) | ||||||
|  | 			r += size | ||||||
|  | 			replaced = append(replaced, c) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		r += 1 | ||||||
|  | 		if r >= len(s) { | ||||||
|  | 			p.bug("Escape sequence at end of string.") | ||||||
|  | 			return "" | ||||||
|  | 		} | ||||||
|  | 		switch s[r] { | ||||||
|  | 		default: | ||||||
|  | 			p.bug("Expected valid escape code after \\, but got %q.", s[r]) | ||||||
|  | 			return "" | ||||||
|  | 		case 'b': | ||||||
|  | 			replaced = append(replaced, rune(0x0008)) | ||||||
|  | 			r += 1 | ||||||
|  | 		case 't': | ||||||
|  | 			replaced = append(replaced, rune(0x0009)) | ||||||
|  | 			r += 1 | ||||||
|  | 		case 'n': | ||||||
|  | 			replaced = append(replaced, rune(0x000A)) | ||||||
|  | 			r += 1 | ||||||
|  | 		case 'f': | ||||||
|  | 			replaced = append(replaced, rune(0x000C)) | ||||||
|  | 			r += 1 | ||||||
|  | 		case 'r': | ||||||
|  | 			replaced = append(replaced, rune(0x000D)) | ||||||
|  | 			r += 1 | ||||||
|  | 		case '"': | ||||||
|  | 			replaced = append(replaced, rune(0x0022)) | ||||||
|  | 			r += 1 | ||||||
|  | 		case '\\': | ||||||
|  | 			replaced = append(replaced, rune(0x005C)) | ||||||
|  | 			r += 1 | ||||||
|  | 		case 'u': | ||||||
|  | 			// At this point, we know we have a Unicode escape of the form
 | ||||||
|  | 			// `uXXXX` at [r, r+5). (Because the lexer guarantees this
 | ||||||
|  | 			// for us.)
 | ||||||
|  | 			escaped := p.asciiEscapeToUnicode(s[r+1 : r+5]) | ||||||
|  | 			replaced = append(replaced, escaped) | ||||||
|  | 			r += 5 | ||||||
|  | 		case 'U': | ||||||
|  | 			// At this point, we know we have a Unicode escape of the form
 | ||||||
|  | 			// `uXXXX` at [r, r+9). (Because the lexer guarantees this
 | ||||||
|  | 			// for us.)
 | ||||||
|  | 			escaped := p.asciiEscapeToUnicode(s[r+1 : r+9]) | ||||||
|  | 			replaced = append(replaced, escaped) | ||||||
|  | 			r += 9 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return string(replaced) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (p *parser) asciiEscapeToUnicode(bs []byte) rune { | ||||||
|  | 	s := string(bs) | ||||||
|  | 	hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32) | ||||||
|  | 	if err != nil { | ||||||
|  | 		p.bug("Could not parse '%s' as a hexadecimal number, but the "+ | ||||||
|  | 			"lexer claims it's OK: %s", s, err) | ||||||
|  | 	} | ||||||
|  | 	if !utf8.ValidRune(rune(hex)) { | ||||||
|  | 		p.panicf("Escaped character '\\u%s' is not valid UTF-8.", s) | ||||||
|  | 	} | ||||||
|  | 	return rune(hex) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func isStringType(ty itemType) bool { | ||||||
|  | 	return ty == itemString || ty == itemMultilineString || | ||||||
|  | 		ty == itemRawString || ty == itemRawMultilineString | ||||||
|  | } | ||||||
|  | @ -0,0 +1,91 @@ | ||||||
|  | package toml | ||||||
|  | 
 | ||||||
|  | // tomlType represents any Go type that corresponds to a TOML type.
 | ||||||
|  | // While the first draft of the TOML spec has a simplistic type system that
 | ||||||
|  | // probably doesn't need this level of sophistication, we seem to be militating
 | ||||||
|  | // toward adding real composite types.
 | ||||||
|  | type tomlType interface { | ||||||
|  | 	typeString() string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // typeEqual accepts any two types and returns true if they are equal.
 | ||||||
|  | func typeEqual(t1, t2 tomlType) bool { | ||||||
|  | 	if t1 == nil || t2 == nil { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	return t1.typeString() == t2.typeString() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func typeIsHash(t tomlType) bool { | ||||||
|  | 	return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type tomlBaseType string | ||||||
|  | 
 | ||||||
|  | func (btype tomlBaseType) typeString() string { | ||||||
|  | 	return string(btype) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (btype tomlBaseType) String() string { | ||||||
|  | 	return btype.typeString() | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	tomlInteger   tomlBaseType = "Integer" | ||||||
|  | 	tomlFloat     tomlBaseType = "Float" | ||||||
|  | 	tomlDatetime  tomlBaseType = "Datetime" | ||||||
|  | 	tomlString    tomlBaseType = "String" | ||||||
|  | 	tomlBool      tomlBaseType = "Bool" | ||||||
|  | 	tomlArray     tomlBaseType = "Array" | ||||||
|  | 	tomlHash      tomlBaseType = "Hash" | ||||||
|  | 	tomlArrayHash tomlBaseType = "ArrayHash" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // typeOfPrimitive returns a tomlType of any primitive value in TOML.
 | ||||||
|  | // Primitive values are: Integer, Float, Datetime, String and Bool.
 | ||||||
|  | //
 | ||||||
|  | // Passing a lexer item other than the following will cause a BUG message
 | ||||||
|  | // to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime.
 | ||||||
|  | func (p *parser) typeOfPrimitive(lexItem item) tomlType { | ||||||
|  | 	switch lexItem.typ { | ||||||
|  | 	case itemInteger: | ||||||
|  | 		return tomlInteger | ||||||
|  | 	case itemFloat: | ||||||
|  | 		return tomlFloat | ||||||
|  | 	case itemDatetime: | ||||||
|  | 		return tomlDatetime | ||||||
|  | 	case itemString: | ||||||
|  | 		return tomlString | ||||||
|  | 	case itemMultilineString: | ||||||
|  | 		return tomlString | ||||||
|  | 	case itemRawString: | ||||||
|  | 		return tomlString | ||||||
|  | 	case itemRawMultilineString: | ||||||
|  | 		return tomlString | ||||||
|  | 	case itemBool: | ||||||
|  | 		return tomlBool | ||||||
|  | 	} | ||||||
|  | 	p.bug("Cannot infer primitive type of lex item '%s'.", lexItem) | ||||||
|  | 	panic("unreachable") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // typeOfArray returns a tomlType for an array given a list of types of its
 | ||||||
|  | // values.
 | ||||||
|  | //
 | ||||||
|  | // In the current spec, if an array is homogeneous, then its type is always
 | ||||||
|  | // "Array". If the array is not homogeneous, an error is generated.
 | ||||||
|  | func (p *parser) typeOfArray(types []tomlType) tomlType { | ||||||
|  | 	// Empty arrays are cool.
 | ||||||
|  | 	if len(types) == 0 { | ||||||
|  | 		return tomlArray | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	theType := types[0] | ||||||
|  | 	for _, t := range types[1:] { | ||||||
|  | 		if !typeEqual(theType, t) { | ||||||
|  | 			p.panicf("Array contains values of type '%s' and '%s', but "+ | ||||||
|  | 				"arrays must be homogeneous.", theType, t) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return tomlArray | ||||||
|  | } | ||||||
|  | @ -0,0 +1,242 @@ | ||||||
|  | package toml | ||||||
|  | 
 | ||||||
|  | // Struct field handling is adapted from code in encoding/json:
 | ||||||
|  | //
 | ||||||
|  | // Copyright 2010 The Go Authors.  All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a BSD-style
 | ||||||
|  | // license that can be found in the Go distribution.
 | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"reflect" | ||||||
|  | 	"sort" | ||||||
|  | 	"sync" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // A field represents a single field found in a struct.
 | ||||||
|  | type field struct { | ||||||
|  | 	name  string       // the name of the field (`toml` tag included)
 | ||||||
|  | 	tag   bool         // whether field has a `toml` tag
 | ||||||
|  | 	index []int        // represents the depth of an anonymous field
 | ||||||
|  | 	typ   reflect.Type // the type of the field
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // byName sorts field by name, breaking ties with depth,
 | ||||||
|  | // then breaking ties with "name came from toml tag", then
 | ||||||
|  | // breaking ties with index sequence.
 | ||||||
|  | type byName []field | ||||||
|  | 
 | ||||||
|  | func (x byName) Len() int { return len(x) } | ||||||
|  | 
 | ||||||
|  | func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] } | ||||||
|  | 
 | ||||||
|  | func (x byName) Less(i, j int) bool { | ||||||
|  | 	if x[i].name != x[j].name { | ||||||
|  | 		return x[i].name < x[j].name | ||||||
|  | 	} | ||||||
|  | 	if len(x[i].index) != len(x[j].index) { | ||||||
|  | 		return len(x[i].index) < len(x[j].index) | ||||||
|  | 	} | ||||||
|  | 	if x[i].tag != x[j].tag { | ||||||
|  | 		return x[i].tag | ||||||
|  | 	} | ||||||
|  | 	return byIndex(x).Less(i, j) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // byIndex sorts field by index sequence.
 | ||||||
|  | type byIndex []field | ||||||
|  | 
 | ||||||
|  | func (x byIndex) Len() int { return len(x) } | ||||||
|  | 
 | ||||||
|  | func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] } | ||||||
|  | 
 | ||||||
|  | func (x byIndex) Less(i, j int) bool { | ||||||
|  | 	for k, xik := range x[i].index { | ||||||
|  | 		if k >= len(x[j].index) { | ||||||
|  | 			return false | ||||||
|  | 		} | ||||||
|  | 		if xik != x[j].index[k] { | ||||||
|  | 			return xik < x[j].index[k] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return len(x[i].index) < len(x[j].index) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // typeFields returns a list of fields that TOML should recognize for the given
 | ||||||
|  | // type. The algorithm is breadth-first search over the set of structs to
 | ||||||
|  | // include - the top struct and then any reachable anonymous structs.
 | ||||||
|  | func typeFields(t reflect.Type) []field { | ||||||
|  | 	// Anonymous fields to explore at the current level and the next.
 | ||||||
|  | 	current := []field{} | ||||||
|  | 	next := []field{{typ: t}} | ||||||
|  | 
 | ||||||
|  | 	// Count of queued names for current level and the next.
 | ||||||
|  | 	count := map[reflect.Type]int{} | ||||||
|  | 	nextCount := map[reflect.Type]int{} | ||||||
|  | 
 | ||||||
|  | 	// Types already visited at an earlier level.
 | ||||||
|  | 	visited := map[reflect.Type]bool{} | ||||||
|  | 
 | ||||||
|  | 	// Fields found.
 | ||||||
|  | 	var fields []field | ||||||
|  | 
 | ||||||
|  | 	for len(next) > 0 { | ||||||
|  | 		current, next = next, current[:0] | ||||||
|  | 		count, nextCount = nextCount, map[reflect.Type]int{} | ||||||
|  | 
 | ||||||
|  | 		for _, f := range current { | ||||||
|  | 			if visited[f.typ] { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			visited[f.typ] = true | ||||||
|  | 
 | ||||||
|  | 			// Scan f.typ for fields to include.
 | ||||||
|  | 			for i := 0; i < f.typ.NumField(); i++ { | ||||||
|  | 				sf := f.typ.Field(i) | ||||||
|  | 				if sf.PkgPath != "" && !sf.Anonymous { // unexported
 | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  | 				opts := getOptions(sf.Tag) | ||||||
|  | 				if opts.skip { | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  | 				index := make([]int, len(f.index)+1) | ||||||
|  | 				copy(index, f.index) | ||||||
|  | 				index[len(f.index)] = i | ||||||
|  | 
 | ||||||
|  | 				ft := sf.Type | ||||||
|  | 				if ft.Name() == "" && ft.Kind() == reflect.Ptr { | ||||||
|  | 					// Follow pointer.
 | ||||||
|  | 					ft = ft.Elem() | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// Record found field and index sequence.
 | ||||||
|  | 				if opts.name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct { | ||||||
|  | 					tagged := opts.name != "" | ||||||
|  | 					name := opts.name | ||||||
|  | 					if name == "" { | ||||||
|  | 						name = sf.Name | ||||||
|  | 					} | ||||||
|  | 					fields = append(fields, field{name, tagged, index, ft}) | ||||||
|  | 					if count[f.typ] > 1 { | ||||||
|  | 						// If there were multiple instances, add a second,
 | ||||||
|  | 						// so that the annihilation code will see a duplicate.
 | ||||||
|  | 						// It only cares about the distinction between 1 or 2,
 | ||||||
|  | 						// so don't bother generating any more copies.
 | ||||||
|  | 						fields = append(fields, fields[len(fields)-1]) | ||||||
|  | 					} | ||||||
|  | 					continue | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				// Record new anonymous struct to explore in next round.
 | ||||||
|  | 				nextCount[ft]++ | ||||||
|  | 				if nextCount[ft] == 1 { | ||||||
|  | 					f := field{name: ft.Name(), index: index, typ: ft} | ||||||
|  | 					next = append(next, f) | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	sort.Sort(byName(fields)) | ||||||
|  | 
 | ||||||
|  | 	// Delete all fields that are hidden by the Go rules for embedded fields,
 | ||||||
|  | 	// except that fields with TOML tags are promoted.
 | ||||||
|  | 
 | ||||||
|  | 	// The fields are sorted in primary order of name, secondary order
 | ||||||
|  | 	// of field index length. Loop over names; for each name, delete
 | ||||||
|  | 	// hidden fields by choosing the one dominant field that survives.
 | ||||||
|  | 	out := fields[:0] | ||||||
|  | 	for advance, i := 0, 0; i < len(fields); i += advance { | ||||||
|  | 		// One iteration per name.
 | ||||||
|  | 		// Find the sequence of fields with the name of this first field.
 | ||||||
|  | 		fi := fields[i] | ||||||
|  | 		name := fi.name | ||||||
|  | 		for advance = 1; i+advance < len(fields); advance++ { | ||||||
|  | 			fj := fields[i+advance] | ||||||
|  | 			if fj.name != name { | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if advance == 1 { // Only one field with this name
 | ||||||
|  | 			out = append(out, fi) | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 		dominant, ok := dominantField(fields[i : i+advance]) | ||||||
|  | 		if ok { | ||||||
|  | 			out = append(out, dominant) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fields = out | ||||||
|  | 	sort.Sort(byIndex(fields)) | ||||||
|  | 
 | ||||||
|  | 	return fields | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // dominantField looks through the fields, all of which are known to
 | ||||||
|  | // have the same name, to find the single field that dominates the
 | ||||||
|  | // others using Go's embedding rules, modified by the presence of
 | ||||||
|  | // TOML tags. If there are multiple top-level fields, the boolean
 | ||||||
|  | // will be false: This condition is an error in Go and we skip all
 | ||||||
|  | // the fields.
 | ||||||
|  | func dominantField(fields []field) (field, bool) { | ||||||
|  | 	// The fields are sorted in increasing index-length order. The winner
 | ||||||
|  | 	// must therefore be one with the shortest index length. Drop all
 | ||||||
|  | 	// longer entries, which is easy: just truncate the slice.
 | ||||||
|  | 	length := len(fields[0].index) | ||||||
|  | 	tagged := -1 // Index of first tagged field.
 | ||||||
|  | 	for i, f := range fields { | ||||||
|  | 		if len(f.index) > length { | ||||||
|  | 			fields = fields[:i] | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		if f.tag { | ||||||
|  | 			if tagged >= 0 { | ||||||
|  | 				// Multiple tagged fields at the same level: conflict.
 | ||||||
|  | 				// Return no field.
 | ||||||
|  | 				return field{}, false | ||||||
|  | 			} | ||||||
|  | 			tagged = i | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if tagged >= 0 { | ||||||
|  | 		return fields[tagged], true | ||||||
|  | 	} | ||||||
|  | 	// All remaining fields have the same length. If there's more than one,
 | ||||||
|  | 	// we have a conflict (two fields named "X" at the same level) and we
 | ||||||
|  | 	// return no field.
 | ||||||
|  | 	if len(fields) > 1 { | ||||||
|  | 		return field{}, false | ||||||
|  | 	} | ||||||
|  | 	return fields[0], true | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var fieldCache struct { | ||||||
|  | 	sync.RWMutex | ||||||
|  | 	m map[reflect.Type][]field | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
 | ||||||
|  | func cachedTypeFields(t reflect.Type) []field { | ||||||
|  | 	fieldCache.RLock() | ||||||
|  | 	f := fieldCache.m[t] | ||||||
|  | 	fieldCache.RUnlock() | ||||||
|  | 	if f != nil { | ||||||
|  | 		return f | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Compute fields without lock.
 | ||||||
|  | 	// Might duplicate effort but won't hold other computations back.
 | ||||||
|  | 	f = typeFields(t) | ||||||
|  | 	if f == nil { | ||||||
|  | 		f = []field{} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fieldCache.Lock() | ||||||
|  | 	if fieldCache.m == nil { | ||||||
|  | 		fieldCache.m = map[reflect.Type][]field{} | ||||||
|  | 	} | ||||||
|  | 	fieldCache.m[t] = f | ||||||
|  | 	fieldCache.Unlock() | ||||||
|  | 	return f | ||||||
|  | } | ||||||
|  | @ -5,6 +5,7 @@ go_library( | ||||||
|     srcs = [ |     srcs = [ | ||||||
|         "clone.go", |         "clone.go", | ||||||
|         "decode.go", |         "decode.go", | ||||||
|  |         "deprecated.go", | ||||||
|         "discard.go", |         "discard.go", | ||||||
|         "encode.go", |         "encode.go", | ||||||
|         "equal.go", |         "equal.go", | ||||||
|  |  | ||||||
|  | @ -186,7 +186,6 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) { | ||||||
| 	if b&0x80 == 0 { | 	if b&0x80 == 0 { | ||||||
| 		goto done | 		goto done | ||||||
| 	} | 	} | ||||||
| 	// x -= 0x80 << 63 // Always zero.
 |  | ||||||
| 
 | 
 | ||||||
| 	return 0, errOverflow | 	return 0, errOverflow | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -0,0 +1,63 @@ | ||||||
|  | // Go support for Protocol Buffers - Google's data interchange format
 | ||||||
|  | //
 | ||||||
|  | // Copyright 2018 The Go Authors.  All rights reserved.
 | ||||||
|  | // https://github.com/golang/protobuf
 | ||||||
|  | //
 | ||||||
|  | // 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.
 | ||||||
|  | 
 | ||||||
|  | package proto | ||||||
|  | 
 | ||||||
|  | import "errors" | ||||||
|  | 
 | ||||||
|  | // Deprecated: do not use.
 | ||||||
|  | type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 } | ||||||
|  | 
 | ||||||
|  | // Deprecated: do not use.
 | ||||||
|  | func GetStats() Stats { return Stats{} } | ||||||
|  | 
 | ||||||
|  | // Deprecated: do not use.
 | ||||||
|  | func MarshalMessageSet(interface{}) ([]byte, error) { | ||||||
|  | 	return nil, errors.New("proto: not implemented") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Deprecated: do not use.
 | ||||||
|  | func UnmarshalMessageSet([]byte, interface{}) error { | ||||||
|  | 	return errors.New("proto: not implemented") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Deprecated: do not use.
 | ||||||
|  | func MarshalMessageSetJSON(interface{}) ([]byte, error) { | ||||||
|  | 	return nil, errors.New("proto: not implemented") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Deprecated: do not use.
 | ||||||
|  | func UnmarshalMessageSetJSON([]byte, interface{}) error { | ||||||
|  | 	return errors.New("proto: not implemented") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Deprecated: do not use.
 | ||||||
|  | func RegisterMessageSetType(Message, int32, string) {} | ||||||
|  | @ -246,7 +246,8 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool { | ||||||
| 			return false | 			return false | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		m1, m2 := e1.value, e2.value | 		m1 := extensionAsLegacyType(e1.value) | ||||||
|  | 		m2 := extensionAsLegacyType(e2.value) | ||||||
| 
 | 
 | ||||||
| 		if m1 == nil && m2 == nil { | 		if m1 == nil && m2 == nil { | ||||||
| 			// Both have only encoded form.
 | 			// Both have only encoded form.
 | ||||||
|  |  | ||||||
|  | @ -185,9 +185,25 @@ type Extension struct { | ||||||
| 	// extension will have only enc set. When such an extension is
 | 	// extension will have only enc set. When such an extension is
 | ||||||
| 	// accessed using GetExtension (or GetExtensions) desc and value
 | 	// accessed using GetExtension (or GetExtensions) desc and value
 | ||||||
| 	// will be set.
 | 	// will be set.
 | ||||||
| 	desc  *ExtensionDesc | 	desc *ExtensionDesc | ||||||
|  | 
 | ||||||
|  | 	// value is a concrete value for the extension field. Let the type of
 | ||||||
|  | 	// desc.ExtensionType be the "API type" and the type of Extension.value
 | ||||||
|  | 	// be the "storage type". The API type and storage type are the same except:
 | ||||||
|  | 	//	* For scalars (except []byte), the API type uses *T,
 | ||||||
|  | 	//	while the storage type uses T.
 | ||||||
|  | 	//	* For repeated fields, the API type uses []T, while the storage type
 | ||||||
|  | 	//	uses *[]T.
 | ||||||
|  | 	//
 | ||||||
|  | 	// The reason for the divergence is so that the storage type more naturally
 | ||||||
|  | 	// matches what is expected of when retrieving the values through the
 | ||||||
|  | 	// protobuf reflection APIs.
 | ||||||
|  | 	//
 | ||||||
|  | 	// The value may only be populated if desc is also populated.
 | ||||||
| 	value interface{} | 	value interface{} | ||||||
| 	enc   []byte | 
 | ||||||
|  | 	// enc is the raw bytes for the extension field.
 | ||||||
|  | 	enc []byte | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // SetRawExtension is for testing only.
 | // SetRawExtension is for testing only.
 | ||||||
|  | @ -334,7 +350,7 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { | ||||||
| 			// descriptors with the same field number.
 | 			// descriptors with the same field number.
 | ||||||
| 			return nil, errors.New("proto: descriptor conflict") | 			return nil, errors.New("proto: descriptor conflict") | ||||||
| 		} | 		} | ||||||
| 		return e.value, nil | 		return extensionAsLegacyType(e.value), nil | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if extension.ExtensionType == nil { | 	if extension.ExtensionType == nil { | ||||||
|  | @ -349,11 +365,11 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) { | ||||||
| 
 | 
 | ||||||
| 	// Remember the decoded version and drop the encoded version.
 | 	// Remember the decoded version and drop the encoded version.
 | ||||||
| 	// That way it is safe to mutate what we return.
 | 	// That way it is safe to mutate what we return.
 | ||||||
| 	e.value = v | 	e.value = extensionAsStorageType(v) | ||||||
| 	e.desc = extension | 	e.desc = extension | ||||||
| 	e.enc = nil | 	e.enc = nil | ||||||
| 	emap[extension.Field] = e | 	emap[extension.Field] = e | ||||||
| 	return e.value, nil | 	return extensionAsLegacyType(e.value), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // defaultExtensionValue returns the default value for extension.
 | // defaultExtensionValue returns the default value for extension.
 | ||||||
|  | @ -488,7 +504,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error | ||||||
| 	} | 	} | ||||||
| 	typ := reflect.TypeOf(extension.ExtensionType) | 	typ := reflect.TypeOf(extension.ExtensionType) | ||||||
| 	if typ != reflect.TypeOf(value) { | 	if typ != reflect.TypeOf(value) { | ||||||
| 		return errors.New("proto: bad extension value type") | 		return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType) | ||||||
| 	} | 	} | ||||||
| 	// nil extension values need to be caught early, because the
 | 	// nil extension values need to be caught early, because the
 | ||||||
| 	// encoder can't distinguish an ErrNil due to a nil extension
 | 	// encoder can't distinguish an ErrNil due to a nil extension
 | ||||||
|  | @ -500,7 +516,7 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	extmap := epb.extensionsWrite() | 	extmap := epb.extensionsWrite() | ||||||
| 	extmap[extension.Field] = Extension{desc: extension, value: value} | 	extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -541,3 +557,51 @@ func RegisterExtension(desc *ExtensionDesc) { | ||||||
| func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { | func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc { | ||||||
| 	return extensionMaps[reflect.TypeOf(pb).Elem()] | 	return extensionMaps[reflect.TypeOf(pb).Elem()] | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // extensionAsLegacyType converts an value in the storage type as the API type.
 | ||||||
|  | // See Extension.value.
 | ||||||
|  | func extensionAsLegacyType(v interface{}) interface{} { | ||||||
|  | 	switch rv := reflect.ValueOf(v); rv.Kind() { | ||||||
|  | 	case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: | ||||||
|  | 		// Represent primitive types as a pointer to the value.
 | ||||||
|  | 		rv2 := reflect.New(rv.Type()) | ||||||
|  | 		rv2.Elem().Set(rv) | ||||||
|  | 		v = rv2.Interface() | ||||||
|  | 	case reflect.Ptr: | ||||||
|  | 		// Represent slice types as the value itself.
 | ||||||
|  | 		switch rv.Type().Elem().Kind() { | ||||||
|  | 		case reflect.Slice: | ||||||
|  | 			if rv.IsNil() { | ||||||
|  | 				v = reflect.Zero(rv.Type().Elem()).Interface() | ||||||
|  | 			} else { | ||||||
|  | 				v = rv.Elem().Interface() | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return v | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // extensionAsStorageType converts an value in the API type as the storage type.
 | ||||||
|  | // See Extension.value.
 | ||||||
|  | func extensionAsStorageType(v interface{}) interface{} { | ||||||
|  | 	switch rv := reflect.ValueOf(v); rv.Kind() { | ||||||
|  | 	case reflect.Ptr: | ||||||
|  | 		// Represent slice types as the value itself.
 | ||||||
|  | 		switch rv.Type().Elem().Kind() { | ||||||
|  | 		case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: | ||||||
|  | 			if rv.IsNil() { | ||||||
|  | 				v = reflect.Zero(rv.Type().Elem()).Interface() | ||||||
|  | 			} else { | ||||||
|  | 				v = rv.Elem().Interface() | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	case reflect.Slice: | ||||||
|  | 		// Represent slice types as a pointer to the value.
 | ||||||
|  | 		if rv.Type().Elem().Kind() != reflect.Uint8 { | ||||||
|  | 			rv2 := reflect.New(rv.Type()) | ||||||
|  | 			rv2.Elem().Set(rv) | ||||||
|  | 			v = rv2.Interface() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return v | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -341,26 +341,6 @@ type Message interface { | ||||||
| 	ProtoMessage() | 	ProtoMessage() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Stats records allocation details about the protocol buffer encoders
 |  | ||||||
| // and decoders.  Useful for tuning the library itself.
 |  | ||||||
| type Stats struct { |  | ||||||
| 	Emalloc uint64 // mallocs in encode
 |  | ||||||
| 	Dmalloc uint64 // mallocs in decode
 |  | ||||||
| 	Encode  uint64 // number of encodes
 |  | ||||||
| 	Decode  uint64 // number of decodes
 |  | ||||||
| 	Chit    uint64 // number of cache hits
 |  | ||||||
| 	Cmiss   uint64 // number of cache misses
 |  | ||||||
| 	Size    uint64 // number of sizes
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Set to true to enable stats collection.
 |  | ||||||
| const collectStats = false |  | ||||||
| 
 |  | ||||||
| var stats Stats |  | ||||||
| 
 |  | ||||||
| // GetStats returns a copy of the global Stats structure.
 |  | ||||||
| func GetStats() Stats { return stats } |  | ||||||
| 
 |  | ||||||
| // A Buffer is a buffer manager for marshaling and unmarshaling
 | // A Buffer is a buffer manager for marshaling and unmarshaling
 | ||||||
| // protocol buffers.  It may be reused between invocations to
 | // protocol buffers.  It may be reused between invocations to
 | ||||||
| // reduce memory usage.  It is not necessary to use a Buffer;
 | // reduce memory usage.  It is not necessary to use a Buffer;
 | ||||||
|  | @ -960,13 +940,19 @@ func isProto3Zero(v reflect.Value) bool { | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ProtoPackageIsVersion2 is referenced from generated protocol buffer files
 | const ( | ||||||
| // to assert that that code is compatible with this version of the proto package.
 | 	// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
 | ||||||
| const ProtoPackageIsVersion2 = true | 	// to assert that that code is compatible with this version of the proto package.
 | ||||||
|  | 	ProtoPackageIsVersion3 = true | ||||||
| 
 | 
 | ||||||
| // ProtoPackageIsVersion1 is referenced from generated protocol buffer files
 | 	// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
 | ||||||
| // to assert that that code is compatible with this version of the proto package.
 | 	// to assert that that code is compatible with this version of the proto package.
 | ||||||
| const ProtoPackageIsVersion1 = true | 	ProtoPackageIsVersion2 = true | ||||||
|  | 
 | ||||||
|  | 	// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
 | ||||||
|  | 	// to assert that that code is compatible with this version of the proto package.
 | ||||||
|  | 	ProtoPackageIsVersion1 = true | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| // InternalMessageInfo is a type used internally by generated .pb.go files.
 | // InternalMessageInfo is a type used internally by generated .pb.go files.
 | ||||||
| // This type is not intended to be used by non-generated code.
 | // This type is not intended to be used by non-generated code.
 | ||||||
|  |  | ||||||
|  | @ -36,13 +36,7 @@ package proto | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" |  | ||||||
| 	"encoding/json" |  | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" |  | ||||||
| 	"reflect" |  | ||||||
| 	"sort" |  | ||||||
| 	"sync" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
 | // errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
 | ||||||
|  | @ -145,46 +139,9 @@ func skipVarint(buf []byte) []byte { | ||||||
| 	return buf[i+1:] | 	return buf[i+1:] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // MarshalMessageSet encodes the extension map represented by m in the message set wire format.
 | // unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
 | ||||||
| // It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
 |  | ||||||
| func MarshalMessageSet(exts interface{}) ([]byte, error) { |  | ||||||
| 	return marshalMessageSet(exts, false) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // marshaMessageSet implements above function, with the opt to turn on / off deterministic during Marshal.
 |  | ||||||
| func marshalMessageSet(exts interface{}, deterministic bool) ([]byte, error) { |  | ||||||
| 	switch exts := exts.(type) { |  | ||||||
| 	case *XXX_InternalExtensions: |  | ||||||
| 		var u marshalInfo |  | ||||||
| 		siz := u.sizeMessageSet(exts) |  | ||||||
| 		b := make([]byte, 0, siz) |  | ||||||
| 		return u.appendMessageSet(b, exts, deterministic) |  | ||||||
| 
 |  | ||||||
| 	case map[int32]Extension: |  | ||||||
| 		// This is an old-style extension map.
 |  | ||||||
| 		// Wrap it in a new-style XXX_InternalExtensions.
 |  | ||||||
| 		ie := XXX_InternalExtensions{ |  | ||||||
| 			p: &struct { |  | ||||||
| 				mu           sync.Mutex |  | ||||||
| 				extensionMap map[int32]Extension |  | ||||||
| 			}{ |  | ||||||
| 				extensionMap: exts, |  | ||||||
| 			}, |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		var u marshalInfo |  | ||||||
| 		siz := u.sizeMessageSet(&ie) |  | ||||||
| 		b := make([]byte, 0, siz) |  | ||||||
| 		return u.appendMessageSet(b, &ie, deterministic) |  | ||||||
| 
 |  | ||||||
| 	default: |  | ||||||
| 		return nil, errors.New("proto: not an extension map") |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
 |  | ||||||
| // It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
 | // It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
 | ||||||
| func UnmarshalMessageSet(buf []byte, exts interface{}) error { | func unmarshalMessageSet(buf []byte, exts interface{}) error { | ||||||
| 	var m map[int32]Extension | 	var m map[int32]Extension | ||||||
| 	switch exts := exts.(type) { | 	switch exts := exts.(type) { | ||||||
| 	case *XXX_InternalExtensions: | 	case *XXX_InternalExtensions: | ||||||
|  | @ -222,93 +179,3 @@ func UnmarshalMessageSet(buf []byte, exts interface{}) error { | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
 |  | ||||||
| // It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
 |  | ||||||
| func MarshalMessageSetJSON(exts interface{}) ([]byte, error) { |  | ||||||
| 	var m map[int32]Extension |  | ||||||
| 	switch exts := exts.(type) { |  | ||||||
| 	case *XXX_InternalExtensions: |  | ||||||
| 		var mu sync.Locker |  | ||||||
| 		m, mu = exts.extensionsRead() |  | ||||||
| 		if m != nil { |  | ||||||
| 			// Keep the extensions map locked until we're done marshaling to prevent
 |  | ||||||
| 			// races between marshaling and unmarshaling the lazily-{en,de}coded
 |  | ||||||
| 			// values.
 |  | ||||||
| 			mu.Lock() |  | ||||||
| 			defer mu.Unlock() |  | ||||||
| 		} |  | ||||||
| 	case map[int32]Extension: |  | ||||||
| 		m = exts |  | ||||||
| 	default: |  | ||||||
| 		return nil, errors.New("proto: not an extension map") |  | ||||||
| 	} |  | ||||||
| 	var b bytes.Buffer |  | ||||||
| 	b.WriteByte('{') |  | ||||||
| 
 |  | ||||||
| 	// Process the map in key order for deterministic output.
 |  | ||||||
| 	ids := make([]int32, 0, len(m)) |  | ||||||
| 	for id := range m { |  | ||||||
| 		ids = append(ids, id) |  | ||||||
| 	} |  | ||||||
| 	sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
 |  | ||||||
| 
 |  | ||||||
| 	for i, id := range ids { |  | ||||||
| 		ext := m[id] |  | ||||||
| 		msd, ok := messageSetMap[id] |  | ||||||
| 		if !ok { |  | ||||||
| 			// Unknown type; we can't render it, so skip it.
 |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if i > 0 && b.Len() > 1 { |  | ||||||
| 			b.WriteByte(',') |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		fmt.Fprintf(&b, `"[%s]":`, msd.name) |  | ||||||
| 
 |  | ||||||
| 		x := ext.value |  | ||||||
| 		if x == nil { |  | ||||||
| 			x = reflect.New(msd.t.Elem()).Interface() |  | ||||||
| 			if err := Unmarshal(ext.enc, x.(Message)); err != nil { |  | ||||||
| 				return nil, err |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		d, err := json.Marshal(x) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, err |  | ||||||
| 		} |  | ||||||
| 		b.Write(d) |  | ||||||
| 	} |  | ||||||
| 	b.WriteByte('}') |  | ||||||
| 	return b.Bytes(), nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
 |  | ||||||
| // It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
 |  | ||||||
| func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error { |  | ||||||
| 	// Common-case fast path.
 |  | ||||||
| 	if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// This is fairly tricky, and it's not clear that it is needed.
 |  | ||||||
| 	return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented") |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // A global registry of types that can be used in a MessageSet.
 |  | ||||||
| 
 |  | ||||||
| var messageSetMap = make(map[int32]messageSetDesc) |  | ||||||
| 
 |  | ||||||
| type messageSetDesc struct { |  | ||||||
| 	t    reflect.Type // pointer to struct
 |  | ||||||
| 	name string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // RegisterMessageSetType is called from the generated code.
 |  | ||||||
| func RegisterMessageSetType(m Message, fieldNum int32, name string) { |  | ||||||
| 	messageSetMap[fieldNum] = messageSetDesc{ |  | ||||||
| 		t:    reflect.TypeOf(m), |  | ||||||
| 		name: name, |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -79,10 +79,13 @@ func toPointer(i *Message) pointer { | ||||||
| 
 | 
 | ||||||
| // toAddrPointer converts an interface to a pointer that points to
 | // toAddrPointer converts an interface to a pointer that points to
 | ||||||
| // the interface data.
 | // the interface data.
 | ||||||
| func toAddrPointer(i *interface{}, isptr bool) pointer { | func toAddrPointer(i *interface{}, isptr, deref bool) pointer { | ||||||
| 	v := reflect.ValueOf(*i) | 	v := reflect.ValueOf(*i) | ||||||
| 	u := reflect.New(v.Type()) | 	u := reflect.New(v.Type()) | ||||||
| 	u.Elem().Set(v) | 	u.Elem().Set(v) | ||||||
|  | 	if deref { | ||||||
|  | 		u = u.Elem() | ||||||
|  | 	} | ||||||
| 	return pointer{v: u} | 	return pointer{v: u} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -85,16 +85,21 @@ func toPointer(i *Message) pointer { | ||||||
| 
 | 
 | ||||||
| // toAddrPointer converts an interface to a pointer that points to
 | // toAddrPointer converts an interface to a pointer that points to
 | ||||||
| // the interface data.
 | // the interface data.
 | ||||||
| func toAddrPointer(i *interface{}, isptr bool) pointer { | func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) { | ||||||
| 	// Super-tricky - read or get the address of data word of interface value.
 | 	// Super-tricky - read or get the address of data word of interface value.
 | ||||||
| 	if isptr { | 	if isptr { | ||||||
| 		// The interface is of pointer type, thus it is a direct interface.
 | 		// The interface is of pointer type, thus it is a direct interface.
 | ||||||
| 		// The data word is the pointer data itself. We take its address.
 | 		// The data word is the pointer data itself. We take its address.
 | ||||||
| 		return pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)} | 		p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)} | ||||||
|  | 	} else { | ||||||
|  | 		// The interface is not of pointer type. The data word is the pointer
 | ||||||
|  | 		// to the data.
 | ||||||
|  | 		p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} | ||||||
| 	} | 	} | ||||||
| 	// The interface is not of pointer type. The data word is the pointer
 | 	if deref { | ||||||
| 	// to the data.
 | 		p.p = *(*unsafe.Pointer)(p.p) | ||||||
| 	return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]} | 	} | ||||||
|  | 	return p | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // valToPointer converts v to a pointer. v must be of pointer type.
 | // valToPointer converts v to a pointer. v must be of pointer type.
 | ||||||
|  |  | ||||||
|  | @ -38,7 +38,6 @@ package proto | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"log" | 	"log" | ||||||
| 	"os" |  | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"strconv" | 	"strconv" | ||||||
|  | @ -194,7 +193,7 @@ func (p *Properties) Parse(s string) { | ||||||
| 	// "bytes,49,opt,name=foo,def=hello!"
 | 	// "bytes,49,opt,name=foo,def=hello!"
 | ||||||
| 	fields := strings.Split(s, ",") // breaks def=, but handled below.
 | 	fields := strings.Split(s, ",") // breaks def=, but handled below.
 | ||||||
| 	if len(fields) < 2 { | 	if len(fields) < 2 { | ||||||
| 		fmt.Fprintf(os.Stderr, "proto: tag has too few fields: %q\n", s) | 		log.Printf("proto: tag has too few fields: %q", s) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -214,7 +213,7 @@ func (p *Properties) Parse(s string) { | ||||||
| 		p.WireType = WireBytes | 		p.WireType = WireBytes | ||||||
| 		// no numeric converter for non-numeric types
 | 		// no numeric converter for non-numeric types
 | ||||||
| 	default: | 	default: | ||||||
| 		fmt.Fprintf(os.Stderr, "proto: tag has unknown wire type: %q\n", s) | 		log.Printf("proto: tag has unknown wire type: %q", s) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -334,9 +333,6 @@ func GetProperties(t reflect.Type) *StructProperties { | ||||||
| 	sprop, ok := propertiesMap[t] | 	sprop, ok := propertiesMap[t] | ||||||
| 	propertiesMu.RUnlock() | 	propertiesMu.RUnlock() | ||||||
| 	if ok { | 	if ok { | ||||||
| 		if collectStats { |  | ||||||
| 			stats.Chit++ |  | ||||||
| 		} |  | ||||||
| 		return sprop | 		return sprop | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -346,17 +342,20 @@ func GetProperties(t reflect.Type) *StructProperties { | ||||||
| 	return sprop | 	return sprop | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type ( | ||||||
|  | 	oneofFuncsIface interface { | ||||||
|  | 		XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) | ||||||
|  | 	} | ||||||
|  | 	oneofWrappersIface interface { | ||||||
|  | 		XXX_OneofWrappers() []interface{} | ||||||
|  | 	} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| // getPropertiesLocked requires that propertiesMu is held.
 | // getPropertiesLocked requires that propertiesMu is held.
 | ||||||
| func getPropertiesLocked(t reflect.Type) *StructProperties { | func getPropertiesLocked(t reflect.Type) *StructProperties { | ||||||
| 	if prop, ok := propertiesMap[t]; ok { | 	if prop, ok := propertiesMap[t]; ok { | ||||||
| 		if collectStats { |  | ||||||
| 			stats.Chit++ |  | ||||||
| 		} |  | ||||||
| 		return prop | 		return prop | ||||||
| 	} | 	} | ||||||
| 	if collectStats { |  | ||||||
| 		stats.Cmiss++ |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	prop := new(StructProperties) | 	prop := new(StructProperties) | ||||||
| 	// in case of recursive protos, fill this in now.
 | 	// in case of recursive protos, fill this in now.
 | ||||||
|  | @ -391,13 +390,14 @@ func getPropertiesLocked(t reflect.Type) *StructProperties { | ||||||
| 	// Re-order prop.order.
 | 	// Re-order prop.order.
 | ||||||
| 	sort.Sort(prop) | 	sort.Sort(prop) | ||||||
| 
 | 
 | ||||||
| 	type oneofMessage interface { | 	var oots []interface{} | ||||||
| 		XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) | 	switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { | ||||||
|  | 	case oneofFuncsIface: | ||||||
|  | 		_, _, _, oots = m.XXX_OneofFuncs() | ||||||
|  | 	case oneofWrappersIface: | ||||||
|  | 		oots = m.XXX_OneofWrappers() | ||||||
| 	} | 	} | ||||||
| 	if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { | 	if len(oots) > 0 { | ||||||
| 		var oots []interface{} |  | ||||||
| 		_, _, _, oots = om.XXX_OneofFuncs() |  | ||||||
| 
 |  | ||||||
| 		// Interpret oneof metadata.
 | 		// Interpret oneof metadata.
 | ||||||
| 		prop.OneofTypes = make(map[string]*OneofProperties) | 		prop.OneofTypes = make(map[string]*OneofProperties) | ||||||
| 		for _, oot := range oots { | 		for _, oot := range oots { | ||||||
|  |  | ||||||
|  | @ -87,6 +87,7 @@ type marshalElemInfo struct { | ||||||
| 	sizer     sizer | 	sizer     sizer | ||||||
| 	marshaler marshaler | 	marshaler marshaler | ||||||
| 	isptr     bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
 | 	isptr     bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
 | ||||||
|  | 	deref     bool // dereference the pointer before operating on it; implies isptr
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
|  | @ -320,8 +321,11 @@ func (u *marshalInfo) computeMarshalInfo() { | ||||||
| 
 | 
 | ||||||
| 	// get oneof implementers
 | 	// get oneof implementers
 | ||||||
| 	var oneofImplementers []interface{} | 	var oneofImplementers []interface{} | ||||||
| 	if m, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok { | 	switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { | ||||||
|  | 	case oneofFuncsIface: | ||||||
| 		_, _, _, oneofImplementers = m.XXX_OneofFuncs() | 		_, _, _, oneofImplementers = m.XXX_OneofFuncs() | ||||||
|  | 	case oneofWrappersIface: | ||||||
|  | 		oneofImplementers = m.XXX_OneofWrappers() | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	n := t.NumField() | 	n := t.NumField() | ||||||
|  | @ -407,13 +411,22 @@ func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo { | ||||||
| 		panic("tag is not an integer") | 		panic("tag is not an integer") | ||||||
| 	} | 	} | ||||||
| 	wt := wiretype(tags[0]) | 	wt := wiretype(tags[0]) | ||||||
|  | 	if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct { | ||||||
|  | 		t = t.Elem() | ||||||
|  | 	} | ||||||
| 	sizer, marshaler := typeMarshaler(t, tags, false, false) | 	sizer, marshaler := typeMarshaler(t, tags, false, false) | ||||||
|  | 	var deref bool | ||||||
|  | 	if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 { | ||||||
|  | 		t = reflect.PtrTo(t) | ||||||
|  | 		deref = true | ||||||
|  | 	} | ||||||
| 	e = &marshalElemInfo{ | 	e = &marshalElemInfo{ | ||||||
| 		wiretag:   uint64(tag)<<3 | wt, | 		wiretag:   uint64(tag)<<3 | wt, | ||||||
| 		tagsize:   SizeVarint(uint64(tag) << 3), | 		tagsize:   SizeVarint(uint64(tag) << 3), | ||||||
| 		sizer:     sizer, | 		sizer:     sizer, | ||||||
| 		marshaler: marshaler, | 		marshaler: marshaler, | ||||||
| 		isptr:     t.Kind() == reflect.Ptr, | 		isptr:     t.Kind() == reflect.Ptr, | ||||||
|  | 		deref:     deref, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// update cache
 | 	// update cache
 | ||||||
|  | @ -448,7 +461,7 @@ func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) { | ||||||
| 
 | 
 | ||||||
| func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) { | func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) { | ||||||
| 	fi.field = toField(f) | 	fi.field = toField(f) | ||||||
| 	fi.wiretag = 1<<31 - 1 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
 | 	fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
 | ||||||
| 	fi.isPointer = true | 	fi.isPointer = true | ||||||
| 	fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f) | 	fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f) | ||||||
| 	fi.oneofElems = make(map[reflect.Type]*marshalElemInfo) | 	fi.oneofElems = make(map[reflect.Type]*marshalElemInfo) | ||||||
|  | @ -476,10 +489,6 @@ func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofI | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type oneofMessage interface { |  | ||||||
| 	XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{}) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // wiretype returns the wire encoding of the type.
 | // wiretype returns the wire encoding of the type.
 | ||||||
| func wiretype(encoding string) uint64 { | func wiretype(encoding string) uint64 { | ||||||
| 	switch encoding { | 	switch encoding { | ||||||
|  | @ -2310,8 +2319,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) { | ||||||
| 			for _, k := range m.MapKeys() { | 			for _, k := range m.MapKeys() { | ||||||
| 				ki := k.Interface() | 				ki := k.Interface() | ||||||
| 				vi := m.MapIndex(k).Interface() | 				vi := m.MapIndex(k).Interface() | ||||||
| 				kaddr := toAddrPointer(&ki, false)             // pointer to key
 | 				kaddr := toAddrPointer(&ki, false, false)      // pointer to key
 | ||||||
| 				vaddr := toAddrPointer(&vi, valIsPtr)          // pointer to value
 | 				vaddr := toAddrPointer(&vi, valIsPtr, false)   // pointer to value
 | ||||||
| 				siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
 | 				siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
 | ||||||
| 				n += siz + SizeVarint(uint64(siz)) + tagsize | 				n += siz + SizeVarint(uint64(siz)) + tagsize | ||||||
| 			} | 			} | ||||||
|  | @ -2329,8 +2338,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) { | ||||||
| 			for _, k := range keys { | 			for _, k := range keys { | ||||||
| 				ki := k.Interface() | 				ki := k.Interface() | ||||||
| 				vi := m.MapIndex(k).Interface() | 				vi := m.MapIndex(k).Interface() | ||||||
| 				kaddr := toAddrPointer(&ki, false)    // pointer to key
 | 				kaddr := toAddrPointer(&ki, false, false)    // pointer to key
 | ||||||
| 				vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
 | 				vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
 | ||||||
| 				b = appendVarint(b, tag) | 				b = appendVarint(b, tag) | ||||||
| 				siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
 | 				siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
 | ||||||
| 				b = appendVarint(b, uint64(siz)) | 				b = appendVarint(b, uint64(siz)) | ||||||
|  | @ -2399,7 +2408,7 @@ func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int { | ||||||
| 		// the last time this function was called.
 | 		// the last time this function was called.
 | ||||||
| 		ei := u.getExtElemInfo(e.desc) | 		ei := u.getExtElemInfo(e.desc) | ||||||
| 		v := e.value | 		v := e.value | ||||||
| 		p := toAddrPointer(&v, ei.isptr) | 		p := toAddrPointer(&v, ei.isptr, ei.deref) | ||||||
| 		n += ei.sizer(p, ei.tagsize) | 		n += ei.sizer(p, ei.tagsize) | ||||||
| 	} | 	} | ||||||
| 	mu.Unlock() | 	mu.Unlock() | ||||||
|  | @ -2434,7 +2443,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de | ||||||
| 
 | 
 | ||||||
| 			ei := u.getExtElemInfo(e.desc) | 			ei := u.getExtElemInfo(e.desc) | ||||||
| 			v := e.value | 			v := e.value | ||||||
| 			p := toAddrPointer(&v, ei.isptr) | 			p := toAddrPointer(&v, ei.isptr, ei.deref) | ||||||
| 			b, err = ei.marshaler(b, p, ei.wiretag, deterministic) | 			b, err = ei.marshaler(b, p, ei.wiretag, deterministic) | ||||||
| 			if !nerr.Merge(err) { | 			if !nerr.Merge(err) { | ||||||
| 				return b, err | 				return b, err | ||||||
|  | @ -2465,7 +2474,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de | ||||||
| 
 | 
 | ||||||
| 		ei := u.getExtElemInfo(e.desc) | 		ei := u.getExtElemInfo(e.desc) | ||||||
| 		v := e.value | 		v := e.value | ||||||
| 		p := toAddrPointer(&v, ei.isptr) | 		p := toAddrPointer(&v, ei.isptr, ei.deref) | ||||||
| 		b, err = ei.marshaler(b, p, ei.wiretag, deterministic) | 		b, err = ei.marshaler(b, p, ei.wiretag, deterministic) | ||||||
| 		if !nerr.Merge(err) { | 		if !nerr.Merge(err) { | ||||||
| 			return b, err | 			return b, err | ||||||
|  | @ -2510,7 +2519,7 @@ func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int { | ||||||
| 
 | 
 | ||||||
| 		ei := u.getExtElemInfo(e.desc) | 		ei := u.getExtElemInfo(e.desc) | ||||||
| 		v := e.value | 		v := e.value | ||||||
| 		p := toAddrPointer(&v, ei.isptr) | 		p := toAddrPointer(&v, ei.isptr, ei.deref) | ||||||
| 		n += ei.sizer(p, 1) // message, tag = 3 (size=1)
 | 		n += ei.sizer(p, 1) // message, tag = 3 (size=1)
 | ||||||
| 	} | 	} | ||||||
| 	mu.Unlock() | 	mu.Unlock() | ||||||
|  | @ -2553,7 +2562,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de | ||||||
| 
 | 
 | ||||||
| 			ei := u.getExtElemInfo(e.desc) | 			ei := u.getExtElemInfo(e.desc) | ||||||
| 			v := e.value | 			v := e.value | ||||||
| 			p := toAddrPointer(&v, ei.isptr) | 			p := toAddrPointer(&v, ei.isptr, ei.deref) | ||||||
| 			b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) | 			b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) | ||||||
| 			if !nerr.Merge(err) { | 			if !nerr.Merge(err) { | ||||||
| 				return b, err | 				return b, err | ||||||
|  | @ -2591,7 +2600,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de | ||||||
| 
 | 
 | ||||||
| 		ei := u.getExtElemInfo(e.desc) | 		ei := u.getExtElemInfo(e.desc) | ||||||
| 		v := e.value | 		v := e.value | ||||||
| 		p := toAddrPointer(&v, ei.isptr) | 		p := toAddrPointer(&v, ei.isptr, ei.deref) | ||||||
| 		b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) | 		b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic) | ||||||
| 		b = append(b, 1<<3|WireEndGroup) | 		b = append(b, 1<<3|WireEndGroup) | ||||||
| 		if !nerr.Merge(err) { | 		if !nerr.Merge(err) { | ||||||
|  | @ -2621,7 +2630,7 @@ func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int { | ||||||
| 
 | 
 | ||||||
| 		ei := u.getExtElemInfo(e.desc) | 		ei := u.getExtElemInfo(e.desc) | ||||||
| 		v := e.value | 		v := e.value | ||||||
| 		p := toAddrPointer(&v, ei.isptr) | 		p := toAddrPointer(&v, ei.isptr, ei.deref) | ||||||
| 		n += ei.sizer(p, ei.tagsize) | 		n += ei.sizer(p, ei.tagsize) | ||||||
| 	} | 	} | ||||||
| 	return n | 	return n | ||||||
|  | @ -2656,7 +2665,7 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ | ||||||
| 
 | 
 | ||||||
| 		ei := u.getExtElemInfo(e.desc) | 		ei := u.getExtElemInfo(e.desc) | ||||||
| 		v := e.value | 		v := e.value | ||||||
| 		p := toAddrPointer(&v, ei.isptr) | 		p := toAddrPointer(&v, ei.isptr, ei.deref) | ||||||
| 		b, err = ei.marshaler(b, p, ei.wiretag, deterministic) | 		b, err = ei.marshaler(b, p, ei.wiretag, deterministic) | ||||||
| 		if !nerr.Merge(err) { | 		if !nerr.Merge(err) { | ||||||
| 			return b, err | 			return b, err | ||||||
|  |  | ||||||
|  | @ -136,7 +136,7 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error { | ||||||
| 		u.computeUnmarshalInfo() | 		u.computeUnmarshalInfo() | ||||||
| 	} | 	} | ||||||
| 	if u.isMessageSet { | 	if u.isMessageSet { | ||||||
| 		return UnmarshalMessageSet(b, m.offset(u.extensions).toExtensions()) | 		return unmarshalMessageSet(b, m.offset(u.extensions).toExtensions()) | ||||||
| 	} | 	} | ||||||
| 	var reqMask uint64 // bitmask of required fields we've seen.
 | 	var reqMask uint64 // bitmask of required fields we've seen.
 | ||||||
| 	var errLater error | 	var errLater error | ||||||
|  | @ -362,46 +362,48 @@ func (u *unmarshalInfo) computeUnmarshalInfo() { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Find any types associated with oneof fields.
 | 	// Find any types associated with oneof fields.
 | ||||||
| 	// TODO: XXX_OneofFuncs returns more info than we need.  Get rid of some of it?
 | 	var oneofImplementers []interface{} | ||||||
| 	fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs") | 	switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) { | ||||||
| 	if fn.IsValid() { | 	case oneofFuncsIface: | ||||||
| 		res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{}
 | 		_, _, _, oneofImplementers = m.XXX_OneofFuncs() | ||||||
| 		for i := res.Len() - 1; i >= 0; i-- { | 	case oneofWrappersIface: | ||||||
| 			v := res.Index(i)                             // interface{}
 | 		oneofImplementers = m.XXX_OneofWrappers() | ||||||
| 			tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X
 | 	} | ||||||
| 			typ := tptr.Elem()                            // Msg_X
 | 	for _, v := range oneofImplementers { | ||||||
|  | 		tptr := reflect.TypeOf(v) // *Msg_X
 | ||||||
|  | 		typ := tptr.Elem()        // Msg_X
 | ||||||
| 
 | 
 | ||||||
| 			f := typ.Field(0) // oneof implementers have one field
 | 		f := typ.Field(0) // oneof implementers have one field
 | ||||||
| 			baseUnmarshal := fieldUnmarshaler(&f) | 		baseUnmarshal := fieldUnmarshaler(&f) | ||||||
| 			tags := strings.Split(f.Tag.Get("protobuf"), ",") | 		tags := strings.Split(f.Tag.Get("protobuf"), ",") | ||||||
| 			fieldNum, err := strconv.Atoi(tags[1]) | 		fieldNum, err := strconv.Atoi(tags[1]) | ||||||
| 			if err != nil { | 		if err != nil { | ||||||
| 				panic("protobuf tag field not an integer: " + tags[1]) | 			panic("protobuf tag field not an integer: " + tags[1]) | ||||||
| 			} | 		} | ||||||
| 			var name string | 		var name string | ||||||
| 			for _, tag := range tags { | 		for _, tag := range tags { | ||||||
| 				if strings.HasPrefix(tag, "name=") { | 			if strings.HasPrefix(tag, "name=") { | ||||||
| 					name = strings.TrimPrefix(tag, "name=") | 				name = strings.TrimPrefix(tag, "name=") | ||||||
| 					break | 				break | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			// Find the oneof field that this struct implements.
 |  | ||||||
| 			// Might take O(n^2) to process all of the oneofs, but who cares.
 |  | ||||||
| 			for _, of := range oneofFields { |  | ||||||
| 				if tptr.Implements(of.ityp) { |  | ||||||
| 					// We have found the corresponding interface for this struct.
 |  | ||||||
| 					// That lets us know where this struct should be stored
 |  | ||||||
| 					// when we encounter it during unmarshaling.
 |  | ||||||
| 					unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) |  | ||||||
| 					u.setTag(fieldNum, of.field, unmarshal, 0, name) |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 
 | ||||||
|  | 		// Find the oneof field that this struct implements.
 | ||||||
|  | 		// Might take O(n^2) to process all of the oneofs, but who cares.
 | ||||||
|  | 		for _, of := range oneofFields { | ||||||
|  | 			if tptr.Implements(of.ityp) { | ||||||
|  | 				// We have found the corresponding interface for this struct.
 | ||||||
|  | 				// That lets us know where this struct should be stored
 | ||||||
|  | 				// when we encounter it during unmarshaling.
 | ||||||
|  | 				unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal) | ||||||
|  | 				u.setTag(fieldNum, of.field, unmarshal, 0, name) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Get extension ranges, if any.
 | 	// Get extension ranges, if any.
 | ||||||
| 	fn = reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") | 	fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray") | ||||||
| 	if fn.IsValid() { | 	if fn.IsValid() { | ||||||
| 		if !u.extensions.IsValid() && !u.oldExtensions.IsValid() { | 		if !u.extensions.IsValid() && !u.oldExtensions.IsValid() { | ||||||
| 			panic("a message with extensions, but no extensions field in " + t.Name()) | 			panic("a message with extensions, but no extensions field in " + t.Name()) | ||||||
|  | @ -1948,7 +1950,7 @@ func encodeVarint(b []byte, x uint64) []byte { | ||||||
| // If there is an error, it returns 0,0.
 | // If there is an error, it returns 0,0.
 | ||||||
| func decodeVarint(b []byte) (uint64, int) { | func decodeVarint(b []byte) (uint64, int) { | ||||||
| 	var x, y uint64 | 	var x, y uint64 | ||||||
| 	if len(b) <= 0 { | 	if len(b) == 0 { | ||||||
| 		goto bad | 		goto bad | ||||||
| 	} | 	} | ||||||
| 	x = uint64(b[0]) | 	x = uint64(b[0]) | ||||||
|  |  | ||||||
|  | @ -1,11 +1,13 @@ | ||||||
| // Code generated by protoc-gen-go. DO NOT EDIT.
 | // Code generated by protoc-gen-go. DO NOT EDIT.
 | ||||||
| // source: google/protobuf/any.proto
 | // source: google/protobuf/any.proto
 | ||||||
| 
 | 
 | ||||||
| package any // import "github.com/golang/protobuf/ptypes/any"
 | package any | ||||||
| 
 | 
 | ||||||
| import proto "github.com/golang/protobuf/proto" | import ( | ||||||
| import fmt "fmt" | 	fmt "fmt" | ||||||
| import math "math" | 	proto "github.com/golang/protobuf/proto" | ||||||
|  | 	math "math" | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| // Reference imports to suppress errors if they are not otherwise used.
 | // Reference imports to suppress errors if they are not otherwise used.
 | ||||||
| var _ = proto.Marshal | var _ = proto.Marshal | ||||||
|  | @ -16,7 +18,7 @@ var _ = math.Inf | ||||||
| // is compatible with the proto package it is being compiled against.
 | // is compatible with the proto package it is being compiled against.
 | ||||||
| // A compilation error at this line likely means your copy of the
 | // A compilation error at this line likely means your copy of the
 | ||||||
| // proto package needs to be updated.
 | // proto package needs to be updated.
 | ||||||
| const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 | ||||||
| 
 | 
 | ||||||
| // `Any` contains an arbitrary serialized protocol buffer message along with a
 | // `Any` contains an arbitrary serialized protocol buffer message along with a
 | ||||||
| // URL that describes the type of the serialized message.
 | // URL that describes the type of the serialized message.
 | ||||||
|  | @ -99,17 +101,18 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package | ||||||
| //     }
 | //     }
 | ||||||
| //
 | //
 | ||||||
| type Any struct { | type Any struct { | ||||||
| 	// A URL/resource name whose content describes the type of the
 | 	// A URL/resource name that uniquely identifies the type of the serialized
 | ||||||
| 	// serialized protocol buffer message.
 | 	// protocol buffer message. The last segment of the URL's path must represent
 | ||||||
|  | 	// the fully qualified name of the type (as in
 | ||||||
|  | 	// `path/google.protobuf.Duration`). The name should be in a canonical form
 | ||||||
|  | 	// (e.g., leading "." is not accepted).
 | ||||||
| 	//
 | 	//
 | ||||||
| 	// For URLs which use the scheme `http`, `https`, or no scheme, the
 | 	// In practice, teams usually precompile into the binary all types that they
 | ||||||
| 	// following restrictions and interpretations apply:
 | 	// expect it to use in the context of Any. However, for URLs which use the
 | ||||||
|  | 	// scheme `http`, `https`, or no scheme, one can optionally set up a type
 | ||||||
|  | 	// server that maps type URLs to message definitions as follows:
 | ||||||
| 	//
 | 	//
 | ||||||
| 	// * If no scheme is provided, `https` is assumed.
 | 	// * If no scheme is provided, `https` is assumed.
 | ||||||
| 	// * The last segment of the URL's path must represent the fully
 |  | ||||||
| 	//   qualified name of the type (as in `path/google.protobuf.Duration`).
 |  | ||||||
| 	//   The name should be in a canonical form (e.g., leading "." is
 |  | ||||||
| 	//   not accepted).
 |  | ||||||
| 	// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
 | 	// * An HTTP GET on the URL must yield a [google.protobuf.Type][]
 | ||||||
| 	//   value in binary format, or produce an error.
 | 	//   value in binary format, or produce an error.
 | ||||||
| 	// * Applications are allowed to cache lookup results based on the
 | 	// * Applications are allowed to cache lookup results based on the
 | ||||||
|  | @ -118,6 +121,10 @@ type Any struct { | ||||||
| 	//   on changes to types. (Use versioned type names to manage
 | 	//   on changes to types. (Use versioned type names to manage
 | ||||||
| 	//   breaking changes.)
 | 	//   breaking changes.)
 | ||||||
| 	//
 | 	//
 | ||||||
|  | 	// Note: this functionality is not currently available in the official
 | ||||||
|  | 	// protobuf release, and it is not used for type URLs beginning with
 | ||||||
|  | 	// type.googleapis.com.
 | ||||||
|  | 	//
 | ||||||
| 	// Schemes other than `http`, `https` (or the empty scheme) might be
 | 	// Schemes other than `http`, `https` (or the empty scheme) might be
 | ||||||
| 	// used with implementation specific semantics.
 | 	// used with implementation specific semantics.
 | ||||||
| 	//
 | 	//
 | ||||||
|  | @ -133,17 +140,19 @@ func (m *Any) Reset()         { *m = Any{} } | ||||||
| func (m *Any) String() string { return proto.CompactTextString(m) } | func (m *Any) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Any) ProtoMessage()    {} | func (*Any) ProtoMessage()    {} | ||||||
| func (*Any) Descriptor() ([]byte, []int) { | func (*Any) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_any_744b9ca530f228db, []int{0} | 	return fileDescriptor_b53526c13ae22eb4, []int{0} | ||||||
| } | } | ||||||
|  | 
 | ||||||
| func (*Any) XXX_WellKnownType() string { return "Any" } | func (*Any) XXX_WellKnownType() string { return "Any" } | ||||||
|  | 
 | ||||||
| func (m *Any) XXX_Unmarshal(b []byte) error { | func (m *Any) XXX_Unmarshal(b []byte) error { | ||||||
| 	return xxx_messageInfo_Any.Unmarshal(m, b) | 	return xxx_messageInfo_Any.Unmarshal(m, b) | ||||||
| } | } | ||||||
| func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
| 	return xxx_messageInfo_Any.Marshal(b, m, deterministic) | 	return xxx_messageInfo_Any.Marshal(b, m, deterministic) | ||||||
| } | } | ||||||
| func (dst *Any) XXX_Merge(src proto.Message) { | func (m *Any) XXX_Merge(src proto.Message) { | ||||||
| 	xxx_messageInfo_Any.Merge(dst, src) | 	xxx_messageInfo_Any.Merge(m, src) | ||||||
| } | } | ||||||
| func (m *Any) XXX_Size() int { | func (m *Any) XXX_Size() int { | ||||||
| 	return xxx_messageInfo_Any.Size(m) | 	return xxx_messageInfo_Any.Size(m) | ||||||
|  | @ -172,9 +181,9 @@ func init() { | ||||||
| 	proto.RegisterType((*Any)(nil), "google.protobuf.Any") | 	proto.RegisterType((*Any)(nil), "google.protobuf.Any") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_any_744b9ca530f228db) } | func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4) } | ||||||
| 
 | 
 | ||||||
| var fileDescriptor_any_744b9ca530f228db = []byte{ | var fileDescriptor_b53526c13ae22eb4 = []byte{ | ||||||
| 	// 185 bytes of a gzipped FileDescriptorProto
 | 	// 185 bytes of a gzipped FileDescriptorProto
 | ||||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f, | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f, | ||||||
| 	0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4, | 	0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4, | ||||||
|  |  | ||||||
|  | @ -120,17 +120,18 @@ option objc_class_prefix = "GPB"; | ||||||
| //     } | //     } | ||||||
| // | // | ||||||
| message Any { | message Any { | ||||||
|   // A URL/resource name whose content describes the type of the |   // A URL/resource name that uniquely identifies the type of the serialized | ||||||
|   // serialized protocol buffer message. |   // protocol buffer message. The last segment of the URL's path must represent | ||||||
|  |   // the fully qualified name of the type (as in | ||||||
|  |   // `path/google.protobuf.Duration`). The name should be in a canonical form | ||||||
|  |   // (e.g., leading "." is not accepted). | ||||||
|   // |   // | ||||||
|   // For URLs which use the scheme `http`, `https`, or no scheme, the |   // In practice, teams usually precompile into the binary all types that they | ||||||
|   // following restrictions and interpretations apply: |   // expect it to use in the context of Any. However, for URLs which use the | ||||||
|  |   // scheme `http`, `https`, or no scheme, one can optionally set up a type | ||||||
|  |   // server that maps type URLs to message definitions as follows: | ||||||
|   // |   // | ||||||
|   // * If no scheme is provided, `https` is assumed. |   // * If no scheme is provided, `https` is assumed. | ||||||
|   // * The last segment of the URL's path must represent the fully |  | ||||||
|   //   qualified name of the type (as in `path/google.protobuf.Duration`). |  | ||||||
|   //   The name should be in a canonical form (e.g., leading "." is |  | ||||||
|   //   not accepted). |  | ||||||
|   // * An HTTP GET on the URL must yield a [google.protobuf.Type][] |   // * An HTTP GET on the URL must yield a [google.protobuf.Type][] | ||||||
|   //   value in binary format, or produce an error. |   //   value in binary format, or produce an error. | ||||||
|   // * Applications are allowed to cache lookup results based on the |   // * Applications are allowed to cache lookup results based on the | ||||||
|  | @ -139,6 +140,10 @@ message Any { | ||||||
|   //   on changes to types. (Use versioned type names to manage |   //   on changes to types. (Use versioned type names to manage | ||||||
|   //   breaking changes.) |   //   breaking changes.) | ||||||
|   // |   // | ||||||
|  |   // Note: this functionality is not currently available in the official | ||||||
|  |   // protobuf release, and it is not used for type URLs beginning with | ||||||
|  |   // type.googleapis.com. | ||||||
|  |   // | ||||||
|   // Schemes other than `http`, `https` (or the empty scheme) might be |   // Schemes other than `http`, `https` (or the empty scheme) might be | ||||||
|   // used with implementation specific semantics. |   // used with implementation specific semantics. | ||||||
|   // |   // | ||||||
|  |  | ||||||
|  | @ -82,7 +82,7 @@ func Duration(p *durpb.Duration) (time.Duration, error) { | ||||||
| 		return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) | 		return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) | ||||||
| 	} | 	} | ||||||
| 	if p.Nanos != 0 { | 	if p.Nanos != 0 { | ||||||
| 		d += time.Duration(p.Nanos) | 		d += time.Duration(p.Nanos) * time.Nanosecond | ||||||
| 		if (d < 0) != (p.Nanos < 0) { | 		if (d < 0) != (p.Nanos < 0) { | ||||||
| 			return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) | 			return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -1,11 +1,13 @@ | ||||||
| // Code generated by protoc-gen-go. DO NOT EDIT.
 | // Code generated by protoc-gen-go. DO NOT EDIT.
 | ||||||
| // source: google/protobuf/duration.proto
 | // source: google/protobuf/duration.proto
 | ||||||
| 
 | 
 | ||||||
| package duration // import "github.com/golang/protobuf/ptypes/duration"
 | package duration | ||||||
| 
 | 
 | ||||||
| import proto "github.com/golang/protobuf/proto" | import ( | ||||||
| import fmt "fmt" | 	fmt "fmt" | ||||||
| import math "math" | 	proto "github.com/golang/protobuf/proto" | ||||||
|  | 	math "math" | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| // Reference imports to suppress errors if they are not otherwise used.
 | // Reference imports to suppress errors if they are not otherwise used.
 | ||||||
| var _ = proto.Marshal | var _ = proto.Marshal | ||||||
|  | @ -16,7 +18,7 @@ var _ = math.Inf | ||||||
| // is compatible with the proto package it is being compiled against.
 | // is compatible with the proto package it is being compiled against.
 | ||||||
| // A compilation error at this line likely means your copy of the
 | // A compilation error at this line likely means your copy of the
 | ||||||
| // proto package needs to be updated.
 | // proto package needs to be updated.
 | ||||||
| const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 | ||||||
| 
 | 
 | ||||||
| // A Duration represents a signed, fixed-length span of time represented
 | // A Duration represents a signed, fixed-length span of time represented
 | ||||||
| // as a count of seconds and fractions of seconds at nanosecond
 | // as a count of seconds and fractions of seconds at nanosecond
 | ||||||
|  | @ -99,17 +101,19 @@ func (m *Duration) Reset()         { *m = Duration{} } | ||||||
| func (m *Duration) String() string { return proto.CompactTextString(m) } | func (m *Duration) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Duration) ProtoMessage()    {} | func (*Duration) ProtoMessage()    {} | ||||||
| func (*Duration) Descriptor() ([]byte, []int) { | func (*Duration) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_duration_e7d612259e3f0613, []int{0} | 	return fileDescriptor_23597b2ebd7ac6c5, []int{0} | ||||||
| } | } | ||||||
|  | 
 | ||||||
| func (*Duration) XXX_WellKnownType() string { return "Duration" } | func (*Duration) XXX_WellKnownType() string { return "Duration" } | ||||||
|  | 
 | ||||||
| func (m *Duration) XXX_Unmarshal(b []byte) error { | func (m *Duration) XXX_Unmarshal(b []byte) error { | ||||||
| 	return xxx_messageInfo_Duration.Unmarshal(m, b) | 	return xxx_messageInfo_Duration.Unmarshal(m, b) | ||||||
| } | } | ||||||
| func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
| 	return xxx_messageInfo_Duration.Marshal(b, m, deterministic) | 	return xxx_messageInfo_Duration.Marshal(b, m, deterministic) | ||||||
| } | } | ||||||
| func (dst *Duration) XXX_Merge(src proto.Message) { | func (m *Duration) XXX_Merge(src proto.Message) { | ||||||
| 	xxx_messageInfo_Duration.Merge(dst, src) | 	xxx_messageInfo_Duration.Merge(m, src) | ||||||
| } | } | ||||||
| func (m *Duration) XXX_Size() int { | func (m *Duration) XXX_Size() int { | ||||||
| 	return xxx_messageInfo_Duration.Size(m) | 	return xxx_messageInfo_Duration.Size(m) | ||||||
|  | @ -138,11 +142,9 @@ func init() { | ||||||
| 	proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") | 	proto.RegisterType((*Duration)(nil), "google.protobuf.Duration") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5) } | ||||||
| 	proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_duration_e7d612259e3f0613) |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| var fileDescriptor_duration_e7d612259e3f0613 = []byte{ | var fileDescriptor_23597b2ebd7ac6c5 = []byte{ | ||||||
| 	// 190 bytes of a gzipped FileDescriptorProto
 | 	// 190 bytes of a gzipped FileDescriptorProto
 | ||||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f, | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f, | ||||||
| 	0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a, | 	0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a, | ||||||
|  |  | ||||||
|  | @ -111,11 +111,9 @@ func TimestampNow() *tspb.Timestamp { | ||||||
| // TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
 | // TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
 | ||||||
| // It returns an error if the resulting Timestamp is invalid.
 | // It returns an error if the resulting Timestamp is invalid.
 | ||||||
| func TimestampProto(t time.Time) (*tspb.Timestamp, error) { | func TimestampProto(t time.Time) (*tspb.Timestamp, error) { | ||||||
| 	seconds := t.Unix() |  | ||||||
| 	nanos := int32(t.Sub(time.Unix(seconds, 0))) |  | ||||||
| 	ts := &tspb.Timestamp{ | 	ts := &tspb.Timestamp{ | ||||||
| 		Seconds: seconds, | 		Seconds: t.Unix(), | ||||||
| 		Nanos:   nanos, | 		Nanos:   int32(t.Nanosecond()), | ||||||
| 	} | 	} | ||||||
| 	if err := validateTimestamp(ts); err != nil { | 	if err := validateTimestamp(ts); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
|  |  | ||||||
|  | @ -1,11 +1,13 @@ | ||||||
| // Code generated by protoc-gen-go. DO NOT EDIT.
 | // Code generated by protoc-gen-go. DO NOT EDIT.
 | ||||||
| // source: google/protobuf/timestamp.proto
 | // source: google/protobuf/timestamp.proto
 | ||||||
| 
 | 
 | ||||||
| package timestamp // import "github.com/golang/protobuf/ptypes/timestamp"
 | package timestamp | ||||||
| 
 | 
 | ||||||
| import proto "github.com/golang/protobuf/proto" | import ( | ||||||
| import fmt "fmt" | 	fmt "fmt" | ||||||
| import math "math" | 	proto "github.com/golang/protobuf/proto" | ||||||
|  | 	math "math" | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| // Reference imports to suppress errors if they are not otherwise used.
 | // Reference imports to suppress errors if they are not otherwise used.
 | ||||||
| var _ = proto.Marshal | var _ = proto.Marshal | ||||||
|  | @ -16,7 +18,7 @@ var _ = math.Inf | ||||||
| // is compatible with the proto package it is being compiled against.
 | // is compatible with the proto package it is being compiled against.
 | ||||||
| // A compilation error at this line likely means your copy of the
 | // A compilation error at this line likely means your copy of the
 | ||||||
| // proto package needs to be updated.
 | // proto package needs to be updated.
 | ||||||
| const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 | ||||||
| 
 | 
 | ||||||
| // A Timestamp represents a point in time independent of any time zone
 | // A Timestamp represents a point in time independent of any time zone
 | ||||||
| // or calendar, represented as seconds and fractions of seconds at
 | // or calendar, represented as seconds and fractions of seconds at
 | ||||||
|  | @ -81,7 +83,9 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package | ||||||
| // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
 | // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
 | ||||||
| // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
 | // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
 | ||||||
| // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
 | // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
 | ||||||
| // is required, though only UTC (as indicated by "Z") is presently supported.
 | // is required. A proto3 JSON serializer should always use UTC (as indicated by
 | ||||||
|  | // "Z") when printing the Timestamp type and a proto3 JSON parser should be
 | ||||||
|  | // able to accept both UTC and other timezones (as indicated by an offset).
 | ||||||
| //
 | //
 | ||||||
| // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
 | // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
 | ||||||
| // 01:30 UTC on January 15, 2017.
 | // 01:30 UTC on January 15, 2017.
 | ||||||
|  | @ -92,8 +96,8 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package | ||||||
| // to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
 | // to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
 | ||||||
| // with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
 | // with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
 | ||||||
| // can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
 | // can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
 | ||||||
| // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--)
 | // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
 | ||||||
| // to obtain a formatter capable of generating timestamps in this format.
 | // ) to obtain a formatter capable of generating timestamps in this format.
 | ||||||
| //
 | //
 | ||||||
| //
 | //
 | ||||||
| type Timestamp struct { | type Timestamp struct { | ||||||
|  | @ -115,17 +119,19 @@ func (m *Timestamp) Reset()         { *m = Timestamp{} } | ||||||
| func (m *Timestamp) String() string { return proto.CompactTextString(m) } | func (m *Timestamp) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Timestamp) ProtoMessage()    {} | func (*Timestamp) ProtoMessage()    {} | ||||||
| func (*Timestamp) Descriptor() ([]byte, []int) { | func (*Timestamp) Descriptor() ([]byte, []int) { | ||||||
| 	return fileDescriptor_timestamp_b826e8e5fba671a8, []int{0} | 	return fileDescriptor_292007bbfe81227e, []int{0} | ||||||
| } | } | ||||||
|  | 
 | ||||||
| func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" } | func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" } | ||||||
|  | 
 | ||||||
| func (m *Timestamp) XXX_Unmarshal(b []byte) error { | func (m *Timestamp) XXX_Unmarshal(b []byte) error { | ||||||
| 	return xxx_messageInfo_Timestamp.Unmarshal(m, b) | 	return xxx_messageInfo_Timestamp.Unmarshal(m, b) | ||||||
| } | } | ||||||
| func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
| 	return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic) | 	return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic) | ||||||
| } | } | ||||||
| func (dst *Timestamp) XXX_Merge(src proto.Message) { | func (m *Timestamp) XXX_Merge(src proto.Message) { | ||||||
| 	xxx_messageInfo_Timestamp.Merge(dst, src) | 	xxx_messageInfo_Timestamp.Merge(m, src) | ||||||
| } | } | ||||||
| func (m *Timestamp) XXX_Size() int { | func (m *Timestamp) XXX_Size() int { | ||||||
| 	return xxx_messageInfo_Timestamp.Size(m) | 	return xxx_messageInfo_Timestamp.Size(m) | ||||||
|  | @ -154,11 +160,9 @@ func init() { | ||||||
| 	proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") | 	proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e) } | ||||||
| 	proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_timestamp_b826e8e5fba671a8) |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| var fileDescriptor_timestamp_b826e8e5fba671a8 = []byte{ | var fileDescriptor_292007bbfe81227e = []byte{ | ||||||
| 	// 191 bytes of a gzipped FileDescriptorProto
 | 	// 191 bytes of a gzipped FileDescriptorProto
 | ||||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f, | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f, | ||||||
| 	0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d, | 	0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d, | ||||||
|  |  | ||||||
|  | @ -103,7 +103,9 @@ option objc_class_prefix = "GPB"; | ||||||
| // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional | // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional | ||||||
| // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), | // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), | ||||||
| // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone | // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone | ||||||
| // is required, though only UTC (as indicated by "Z") is presently supported. | // is required. A proto3 JSON serializer should always use UTC (as indicated by | ||||||
|  | // "Z") when printing the Timestamp type and a proto3 JSON parser should be | ||||||
|  | // able to accept both UTC and other timezones (as indicated by an offset). | ||||||
| // | // | ||||||
| // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past | // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past | ||||||
| // 01:30 UTC on January 15, 2017. | // 01:30 UTC on January 15, 2017. | ||||||
|  | @ -114,8 +116,8 @@ option objc_class_prefix = "GPB"; | ||||||
| // to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) | // to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) | ||||||
| // with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one | // with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one | ||||||
| // can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( | // can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( | ||||||
| // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--) | // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime-- | ||||||
| // to obtain a formatter capable of generating timestamps in this format. | // ) to obtain a formatter capable of generating timestamps in this format. | ||||||
| // | // | ||||||
| // | // | ||||||
| message Timestamp { | message Timestamp { | ||||||
|  |  | ||||||
|  | @ -7105,15 +7105,15 @@ func (m *Any) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of ApiKeySecurity suitable for JSON or YAML export.
 | // ToRawInfo returns a description of ApiKeySecurity suitable for JSON or YAML export.
 | ||||||
| func (m *ApiKeySecurity) ToRawInfo() interface{} { | func (m *ApiKeySecurity) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Type != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | 		return info | ||||||
| 	} |  | ||||||
| 	if m.Name != "" { |  | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) |  | ||||||
| 	} |  | ||||||
| 	if m.In != "" { |  | ||||||
| 		info = append(info, yaml.MapItem{Key: "in", Value: m.In}) |  | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "in", Value: m.In}) | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
|  | @ -7129,9 +7129,11 @@ func (m *ApiKeySecurity) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of BasicAuthenticationSecurity suitable for JSON or YAML export.
 | // ToRawInfo returns a description of BasicAuthenticationSecurity suitable for JSON or YAML export.
 | ||||||
| func (m *BasicAuthenticationSecurity) ToRawInfo() interface{} { | func (m *BasicAuthenticationSecurity) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Type != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | 		return info | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
|  | @ -7147,21 +7149,21 @@ func (m *BasicAuthenticationSecurity) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of BodyParameter suitable for JSON or YAML export.
 | // ToRawInfo returns a description of BodyParameter suitable for JSON or YAML export.
 | ||||||
| func (m *BodyParameter) ToRawInfo() interface{} { | func (m *BodyParameter) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
| 	if m.Name != "" { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 	info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	// always include this required field.
 | ||||||
| 	if m.In != "" { | 	info = append(info, yaml.MapItem{Key: "in", Value: m.In}) | ||||||
| 		info = append(info, yaml.MapItem{Key: "in", Value: m.In}) |  | ||||||
| 	} |  | ||||||
| 	if m.Required != false { | 	if m.Required != false { | ||||||
| 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | ||||||
| 	} | 	} | ||||||
| 	if m.Schema != nil { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()}) | 	info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()}) | ||||||
| 	} |  | ||||||
| 	// &{Name:schema Type:Schema StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | 	// &{Name:schema Type:Schema StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | ||||||
| 	if m.VendorExtension != nil { | 	if m.VendorExtension != nil { | ||||||
| 		for _, item := range m.VendorExtension { | 		for _, item := range m.VendorExtension { | ||||||
|  | @ -7175,6 +7177,9 @@ func (m *BodyParameter) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Contact suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Contact suitable for JSON or YAML export.
 | ||||||
| func (m *Contact) ToRawInfo() interface{} { | func (m *Contact) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7196,6 +7201,9 @@ func (m *Contact) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Default suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Default suitable for JSON or YAML export.
 | ||||||
| func (m *Default) ToRawInfo() interface{} { | func (m *Default) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -7208,6 +7216,9 @@ func (m *Default) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Definitions suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Definitions suitable for JSON or YAML export.
 | ||||||
| func (m *Definitions) ToRawInfo() interface{} { | func (m *Definitions) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -7220,12 +7231,13 @@ func (m *Definitions) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Document suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Document suitable for JSON or YAML export.
 | ||||||
| func (m *Document) ToRawInfo() interface{} { | func (m *Document) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Swagger != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "swagger", Value: m.Swagger}) | 		return info | ||||||
| 	} |  | ||||||
| 	if m.Info != nil { |  | ||||||
| 		info = append(info, yaml.MapItem{Key: "info", Value: m.Info.ToRawInfo()}) |  | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "swagger", Value: m.Swagger}) | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "info", Value: m.Info.ToRawInfo()}) | ||||||
| 	// &{Name:info Type:Info StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | 	// &{Name:info Type:Info StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | ||||||
| 	if m.Host != "" { | 	if m.Host != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "host", Value: m.Host}) | 		info = append(info, yaml.MapItem{Key: "host", Value: m.Host}) | ||||||
|  | @ -7242,9 +7254,8 @@ func (m *Document) ToRawInfo() interface{} { | ||||||
| 	if len(m.Produces) != 0 { | 	if len(m.Produces) != 0 { | ||||||
| 		info = append(info, yaml.MapItem{Key: "produces", Value: m.Produces}) | 		info = append(info, yaml.MapItem{Key: "produces", Value: m.Produces}) | ||||||
| 	} | 	} | ||||||
| 	if m.Paths != nil { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "paths", Value: m.Paths.ToRawInfo()}) | 	info = append(info, yaml.MapItem{Key: "paths", Value: m.Paths.ToRawInfo()}) | ||||||
| 	} |  | ||||||
| 	// &{Name:paths Type:Paths StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | 	// &{Name:paths Type:Paths StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | ||||||
| 	if m.Definitions != nil { | 	if m.Definitions != nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "definitions", Value: m.Definitions.ToRawInfo()}) | 		info = append(info, yaml.MapItem{Key: "definitions", Value: m.Definitions.ToRawInfo()}) | ||||||
|  | @ -7294,6 +7305,9 @@ func (m *Document) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Examples suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Examples suitable for JSON or YAML export.
 | ||||||
| func (m *Examples) ToRawInfo() interface{} { | func (m *Examples) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -7306,12 +7320,14 @@ func (m *Examples) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of ExternalDocs suitable for JSON or YAML export.
 | // ToRawInfo returns a description of ExternalDocs suitable for JSON or YAML export.
 | ||||||
| func (m *ExternalDocs) ToRawInfo() interface{} { | func (m *ExternalDocs) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
| 	if m.Url != "" { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "url", Value: m.Url}) | 	info = append(info, yaml.MapItem{Key: "url", Value: m.Url}) | ||||||
| 	} |  | ||||||
| 	if m.VendorExtension != nil { | 	if m.VendorExtension != nil { | ||||||
| 		for _, item := range m.VendorExtension { | 		for _, item := range m.VendorExtension { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -7324,6 +7340,9 @@ func (m *ExternalDocs) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of FileSchema suitable for JSON or YAML export.
 | // ToRawInfo returns a description of FileSchema suitable for JSON or YAML export.
 | ||||||
| func (m *FileSchema) ToRawInfo() interface{} { | func (m *FileSchema) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Format != "" { | 	if m.Format != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "format", Value: m.Format}) | 		info = append(info, yaml.MapItem{Key: "format", Value: m.Format}) | ||||||
| 	} | 	} | ||||||
|  | @ -7340,9 +7359,8 @@ func (m *FileSchema) ToRawInfo() interface{} { | ||||||
| 	if len(m.Required) != 0 { | 	if len(m.Required) != 0 { | ||||||
| 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | ||||||
| 	} | 	} | ||||||
| 	if m.Type != "" { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | 	info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | ||||||
| 	} |  | ||||||
| 	if m.ReadOnly != false { | 	if m.ReadOnly != false { | ||||||
| 		info = append(info, yaml.MapItem{Key: "readOnly", Value: m.ReadOnly}) | 		info = append(info, yaml.MapItem{Key: "readOnly", Value: m.ReadOnly}) | ||||||
| 	} | 	} | ||||||
|  | @ -7366,6 +7384,9 @@ func (m *FileSchema) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of FormDataParameterSubSchema suitable for JSON or YAML export.
 | // ToRawInfo returns a description of FormDataParameterSubSchema suitable for JSON or YAML export.
 | ||||||
| func (m *FormDataParameterSubSchema) ToRawInfo() interface{} { | func (m *FormDataParameterSubSchema) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Required != false { | 	if m.Required != false { | ||||||
| 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | ||||||
| 	} | 	} | ||||||
|  | @ -7451,9 +7472,11 @@ func (m *FormDataParameterSubSchema) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Header suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Header suitable for JSON or YAML export.
 | ||||||
| func (m *Header) ToRawInfo() interface{} { | func (m *Header) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Type != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | 		return info | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | ||||||
| 	if m.Format != "" { | 	if m.Format != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "format", Value: m.Format}) | 		info = append(info, yaml.MapItem{Key: "format", Value: m.Format}) | ||||||
| 	} | 	} | ||||||
|  | @ -7524,6 +7547,9 @@ func (m *Header) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of HeaderParameterSubSchema suitable for JSON or YAML export.
 | // ToRawInfo returns a description of HeaderParameterSubSchema suitable for JSON or YAML export.
 | ||||||
| func (m *HeaderParameterSubSchema) ToRawInfo() interface{} { | func (m *HeaderParameterSubSchema) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Required != false { | 	if m.Required != false { | ||||||
| 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | ||||||
| 	} | 	} | ||||||
|  | @ -7606,6 +7632,9 @@ func (m *HeaderParameterSubSchema) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Headers suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Headers suitable for JSON or YAML export.
 | ||||||
| func (m *Headers) ToRawInfo() interface{} { | func (m *Headers) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -7618,12 +7647,13 @@ func (m *Headers) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Info suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Info suitable for JSON or YAML export.
 | ||||||
| func (m *Info) ToRawInfo() interface{} { | func (m *Info) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Title != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "title", Value: m.Title}) | 		return info | ||||||
| 	} |  | ||||||
| 	if m.Version != "" { |  | ||||||
| 		info = append(info, yaml.MapItem{Key: "version", Value: m.Version}) |  | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "title", Value: m.Title}) | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "version", Value: m.Version}) | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
|  | @ -7650,6 +7680,9 @@ func (m *Info) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of ItemsItem suitable for JSON or YAML export.
 | // ToRawInfo returns a description of ItemsItem suitable for JSON or YAML export.
 | ||||||
| func (m *ItemsItem) ToRawInfo() interface{} { | func (m *ItemsItem) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if len(m.Schema) != 0 { | 	if len(m.Schema) != 0 { | ||||||
| 		items := make([]interface{}, 0) | 		items := make([]interface{}, 0) | ||||||
| 		for _, item := range m.Schema { | 		for _, item := range m.Schema { | ||||||
|  | @ -7664,9 +7697,11 @@ func (m *ItemsItem) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of JsonReference suitable for JSON or YAML export.
 | // ToRawInfo returns a description of JsonReference suitable for JSON or YAML export.
 | ||||||
| func (m *JsonReference) ToRawInfo() interface{} { | func (m *JsonReference) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.XRef != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef}) | 		return info | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef}) | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
|  | @ -7676,9 +7711,11 @@ func (m *JsonReference) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of License suitable for JSON or YAML export.
 | // ToRawInfo returns a description of License suitable for JSON or YAML export.
 | ||||||
| func (m *License) ToRawInfo() interface{} { | func (m *License) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Name != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		return info | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	if m.Url != "" { | 	if m.Url != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "url", Value: m.Url}) | 		info = append(info, yaml.MapItem{Key: "url", Value: m.Url}) | ||||||
| 	} | 	} | ||||||
|  | @ -7694,6 +7731,9 @@ func (m *License) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedAny suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedAny suitable for JSON or YAML export.
 | ||||||
| func (m *NamedAny) ToRawInfo() interface{} { | func (m *NamedAny) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7704,6 +7744,9 @@ func (m *NamedAny) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedHeader suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedHeader suitable for JSON or YAML export.
 | ||||||
| func (m *NamedHeader) ToRawInfo() interface{} { | func (m *NamedHeader) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7714,6 +7757,9 @@ func (m *NamedHeader) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedParameter suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedParameter suitable for JSON or YAML export.
 | ||||||
| func (m *NamedParameter) ToRawInfo() interface{} { | func (m *NamedParameter) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7724,6 +7770,9 @@ func (m *NamedParameter) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedPathItem suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedPathItem suitable for JSON or YAML export.
 | ||||||
| func (m *NamedPathItem) ToRawInfo() interface{} { | func (m *NamedPathItem) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7734,6 +7783,9 @@ func (m *NamedPathItem) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedResponse suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedResponse suitable for JSON or YAML export.
 | ||||||
| func (m *NamedResponse) ToRawInfo() interface{} { | func (m *NamedResponse) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7744,6 +7796,9 @@ func (m *NamedResponse) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedResponseValue suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedResponseValue suitable for JSON or YAML export.
 | ||||||
| func (m *NamedResponseValue) ToRawInfo() interface{} { | func (m *NamedResponseValue) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7754,6 +7809,9 @@ func (m *NamedResponseValue) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedSchema suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedSchema suitable for JSON or YAML export.
 | ||||||
| func (m *NamedSchema) ToRawInfo() interface{} { | func (m *NamedSchema) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7764,6 +7822,9 @@ func (m *NamedSchema) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedSecurityDefinitionsItem suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedSecurityDefinitionsItem suitable for JSON or YAML export.
 | ||||||
| func (m *NamedSecurityDefinitionsItem) ToRawInfo() interface{} { | func (m *NamedSecurityDefinitionsItem) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7774,6 +7835,9 @@ func (m *NamedSecurityDefinitionsItem) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedString suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedString suitable for JSON or YAML export.
 | ||||||
| func (m *NamedString) ToRawInfo() interface{} { | func (m *NamedString) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7786,6 +7850,9 @@ func (m *NamedString) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of NamedStringArray suitable for JSON or YAML export.
 | // ToRawInfo returns a description of NamedStringArray suitable for JSON or YAML export.
 | ||||||
| func (m *NamedStringArray) ToRawInfo() interface{} { | func (m *NamedStringArray) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  | @ -7823,22 +7890,21 @@ func (m *NonBodyParameter) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Oauth2AccessCodeSecurity suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Oauth2AccessCodeSecurity suitable for JSON or YAML export.
 | ||||||
| func (m *Oauth2AccessCodeSecurity) ToRawInfo() interface{} { | func (m *Oauth2AccessCodeSecurity) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Type != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | 		return info | ||||||
| 	} |  | ||||||
| 	if m.Flow != "" { |  | ||||||
| 		info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow}) |  | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow}) | ||||||
| 	if m.Scopes != nil { | 	if m.Scopes != nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()}) | 		info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()}) | ||||||
| 	} | 	} | ||||||
| 	// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | 	// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | ||||||
| 	if m.AuthorizationUrl != "" { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl}) | 	info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl}) | ||||||
| 	} | 	// always include this required field.
 | ||||||
| 	if m.TokenUrl != "" { | 	info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl}) | ||||||
| 		info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl}) |  | ||||||
| 	} |  | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
|  | @ -7854,19 +7920,19 @@ func (m *Oauth2AccessCodeSecurity) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Oauth2ApplicationSecurity suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Oauth2ApplicationSecurity suitable for JSON or YAML export.
 | ||||||
| func (m *Oauth2ApplicationSecurity) ToRawInfo() interface{} { | func (m *Oauth2ApplicationSecurity) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Type != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | 		return info | ||||||
| 	} |  | ||||||
| 	if m.Flow != "" { |  | ||||||
| 		info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow}) |  | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow}) | ||||||
| 	if m.Scopes != nil { | 	if m.Scopes != nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()}) | 		info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()}) | ||||||
| 	} | 	} | ||||||
| 	// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | 	// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | ||||||
| 	if m.TokenUrl != "" { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl}) | 	info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl}) | ||||||
| 	} |  | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
|  | @ -7882,19 +7948,19 @@ func (m *Oauth2ApplicationSecurity) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Oauth2ImplicitSecurity suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Oauth2ImplicitSecurity suitable for JSON or YAML export.
 | ||||||
| func (m *Oauth2ImplicitSecurity) ToRawInfo() interface{} { | func (m *Oauth2ImplicitSecurity) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Type != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | 		return info | ||||||
| 	} |  | ||||||
| 	if m.Flow != "" { |  | ||||||
| 		info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow}) |  | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow}) | ||||||
| 	if m.Scopes != nil { | 	if m.Scopes != nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()}) | 		info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()}) | ||||||
| 	} | 	} | ||||||
| 	// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | 	// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | ||||||
| 	if m.AuthorizationUrl != "" { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl}) | 	info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl}) | ||||||
| 	} |  | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
|  | @ -7910,19 +7976,19 @@ func (m *Oauth2ImplicitSecurity) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Oauth2PasswordSecurity suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Oauth2PasswordSecurity suitable for JSON or YAML export.
 | ||||||
| func (m *Oauth2PasswordSecurity) ToRawInfo() interface{} { | func (m *Oauth2PasswordSecurity) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Type != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | 		return info | ||||||
| 	} |  | ||||||
| 	if m.Flow != "" { |  | ||||||
| 		info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow}) |  | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow}) | ||||||
| 	if m.Scopes != nil { | 	if m.Scopes != nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()}) | 		info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()}) | ||||||
| 	} | 	} | ||||||
| 	// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | 	// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | ||||||
| 	if m.TokenUrl != "" { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl}) | 	info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl}) | ||||||
| 	} |  | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
|  | @ -7938,6 +8004,9 @@ func (m *Oauth2PasswordSecurity) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Oauth2Scopes suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Oauth2Scopes suitable for JSON or YAML export.
 | ||||||
| func (m *Oauth2Scopes) ToRawInfo() interface{} { | func (m *Oauth2Scopes) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	// &{Name:additionalProperties Type:NamedString StringEnumValues:[] MapType:string Repeated:true Pattern: Implicit:true Description:}
 | 	// &{Name:additionalProperties Type:NamedString StringEnumValues:[] MapType:string Repeated:true Pattern: Implicit:true Description:}
 | ||||||
| 	return info | 	return info | ||||||
| } | } | ||||||
|  | @ -7945,6 +8014,9 @@ func (m *Oauth2Scopes) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Operation suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Operation suitable for JSON or YAML export.
 | ||||||
| func (m *Operation) ToRawInfo() interface{} { | func (m *Operation) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if len(m.Tags) != 0 { | 	if len(m.Tags) != 0 { | ||||||
| 		info = append(info, yaml.MapItem{Key: "tags", Value: m.Tags}) | 		info = append(info, yaml.MapItem{Key: "tags", Value: m.Tags}) | ||||||
| 	} | 	} | ||||||
|  | @ -7975,9 +8047,8 @@ func (m *Operation) ToRawInfo() interface{} { | ||||||
| 		info = append(info, yaml.MapItem{Key: "parameters", Value: items}) | 		info = append(info, yaml.MapItem{Key: "parameters", Value: items}) | ||||||
| 	} | 	} | ||||||
| 	// &{Name:parameters Type:ParametersItem StringEnumValues:[] MapType: Repeated:true Pattern: Implicit:false Description:The parameters needed to send a valid API call.}
 | 	// &{Name:parameters Type:ParametersItem StringEnumValues:[] MapType: Repeated:true Pattern: Implicit:false Description:The parameters needed to send a valid API call.}
 | ||||||
| 	if m.Responses != nil { | 	// always include this required field.
 | ||||||
| 		info = append(info, yaml.MapItem{Key: "responses", Value: m.Responses.ToRawInfo()}) | 	info = append(info, yaml.MapItem{Key: "responses", Value: m.Responses.ToRawInfo()}) | ||||||
| 	} |  | ||||||
| 	// &{Name:responses Type:Responses StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | 	// &{Name:responses Type:Responses StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
 | ||||||
| 	if len(m.Schemes) != 0 { | 	if len(m.Schemes) != 0 { | ||||||
| 		info = append(info, yaml.MapItem{Key: "schemes", Value: m.Schemes}) | 		info = append(info, yaml.MapItem{Key: "schemes", Value: m.Schemes}) | ||||||
|  | @ -8022,6 +8093,9 @@ func (m *Parameter) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of ParameterDefinitions suitable for JSON or YAML export.
 | // ToRawInfo returns a description of ParameterDefinitions suitable for JSON or YAML export.
 | ||||||
| func (m *ParameterDefinitions) ToRawInfo() interface{} { | func (m *ParameterDefinitions) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -8051,6 +8125,9 @@ func (m *ParametersItem) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of PathItem suitable for JSON or YAML export.
 | // ToRawInfo returns a description of PathItem suitable for JSON or YAML export.
 | ||||||
| func (m *PathItem) ToRawInfo() interface{} { | func (m *PathItem) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.XRef != "" { | 	if m.XRef != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef}) | 		info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef}) | ||||||
| 	} | 	} | ||||||
|  | @ -8102,9 +8179,11 @@ func (m *PathItem) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of PathParameterSubSchema suitable for JSON or YAML export.
 | // ToRawInfo returns a description of PathParameterSubSchema suitable for JSON or YAML export.
 | ||||||
| func (m *PathParameterSubSchema) ToRawInfo() interface{} { | func (m *PathParameterSubSchema) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Required != false { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | 		return info | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | ||||||
| 	if m.In != "" { | 	if m.In != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "in", Value: m.In}) | 		info = append(info, yaml.MapItem{Key: "in", Value: m.In}) | ||||||
| 	} | 	} | ||||||
|  | @ -8184,6 +8263,9 @@ func (m *PathParameterSubSchema) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Paths suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Paths suitable for JSON or YAML export.
 | ||||||
| func (m *Paths) ToRawInfo() interface{} { | func (m *Paths) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.VendorExtension != nil { | 	if m.VendorExtension != nil { | ||||||
| 		for _, item := range m.VendorExtension { | 		for _, item := range m.VendorExtension { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -8202,6 +8284,9 @@ func (m *Paths) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of PrimitivesItems suitable for JSON or YAML export.
 | // ToRawInfo returns a description of PrimitivesItems suitable for JSON or YAML export.
 | ||||||
| func (m *PrimitivesItems) ToRawInfo() interface{} { | func (m *PrimitivesItems) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Type != "" { | 	if m.Type != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | 		info = append(info, yaml.MapItem{Key: "type", Value: m.Type}) | ||||||
| 	} | 	} | ||||||
|  | @ -8272,6 +8357,9 @@ func (m *PrimitivesItems) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Properties suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Properties suitable for JSON or YAML export.
 | ||||||
| func (m *Properties) ToRawInfo() interface{} { | func (m *Properties) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -8284,6 +8372,9 @@ func (m *Properties) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of QueryParameterSubSchema suitable for JSON or YAML export.
 | // ToRawInfo returns a description of QueryParameterSubSchema suitable for JSON or YAML export.
 | ||||||
| func (m *QueryParameterSubSchema) ToRawInfo() interface{} { | func (m *QueryParameterSubSchema) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Required != false { | 	if m.Required != false { | ||||||
| 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | 		info = append(info, yaml.MapItem{Key: "required", Value: m.Required}) | ||||||
| 	} | 	} | ||||||
|  | @ -8369,9 +8460,11 @@ func (m *QueryParameterSubSchema) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Response suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Response suitable for JSON or YAML export.
 | ||||||
| func (m *Response) ToRawInfo() interface{} { | func (m *Response) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Description != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		return info | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	if m.Schema != nil { | 	if m.Schema != nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()}) | 		info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()}) | ||||||
| 	} | 	} | ||||||
|  | @ -8396,6 +8489,9 @@ func (m *Response) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of ResponseDefinitions suitable for JSON or YAML export.
 | // ToRawInfo returns a description of ResponseDefinitions suitable for JSON or YAML export.
 | ||||||
| func (m *ResponseDefinitions) ToRawInfo() interface{} { | func (m *ResponseDefinitions) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -8425,6 +8521,9 @@ func (m *ResponseValue) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Responses suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Responses suitable for JSON or YAML export.
 | ||||||
| func (m *Responses) ToRawInfo() interface{} { | func (m *Responses) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.ResponseCode != nil { | 	if m.ResponseCode != nil { | ||||||
| 		for _, item := range m.ResponseCode { | 		for _, item := range m.ResponseCode { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -8443,6 +8542,9 @@ func (m *Responses) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Schema suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Schema suitable for JSON or YAML export.
 | ||||||
| func (m *Schema) ToRawInfo() interface{} { | func (m *Schema) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.XRef != "" { | 	if m.XRef != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef}) | 		info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef}) | ||||||
| 	} | 	} | ||||||
|  | @ -8588,6 +8690,9 @@ func (m *SchemaItem) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of SecurityDefinitions suitable for JSON or YAML export.
 | // ToRawInfo returns a description of SecurityDefinitions suitable for JSON or YAML export.
 | ||||||
| func (m *SecurityDefinitions) ToRawInfo() interface{} { | func (m *SecurityDefinitions) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -8637,6 +8742,9 @@ func (m *SecurityDefinitionsItem) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of SecurityRequirement suitable for JSON or YAML export.
 | // ToRawInfo returns a description of SecurityRequirement suitable for JSON or YAML export.
 | ||||||
| func (m *SecurityRequirement) ToRawInfo() interface{} { | func (m *SecurityRequirement) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -8654,9 +8762,11 @@ func (m *StringArray) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Tag suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Tag suitable for JSON or YAML export.
 | ||||||
| func (m *Tag) ToRawInfo() interface{} { | func (m *Tag) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
| 	if m.Name != "" { | 	if m == nil { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		return info | ||||||
| 	} | 	} | ||||||
|  | 	// always include this required field.
 | ||||||
|  | 	info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	if m.Description != "" { | 	if m.Description != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | 		info = append(info, yaml.MapItem{Key: "description", Value: m.Description}) | ||||||
| 	} | 	} | ||||||
|  | @ -8676,6 +8786,9 @@ func (m *Tag) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of TypeItem suitable for JSON or YAML export.
 | // ToRawInfo returns a description of TypeItem suitable for JSON or YAML export.
 | ||||||
| func (m *TypeItem) ToRawInfo() interface{} { | func (m *TypeItem) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if len(m.Value) != 0 { | 	if len(m.Value) != 0 { | ||||||
| 		info = append(info, yaml.MapItem{Key: "value", Value: m.Value}) | 		info = append(info, yaml.MapItem{Key: "value", Value: m.Value}) | ||||||
| 	} | 	} | ||||||
|  | @ -8685,6 +8798,9 @@ func (m *TypeItem) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of VendorExtension suitable for JSON or YAML export.
 | // ToRawInfo returns a description of VendorExtension suitable for JSON or YAML export.
 | ||||||
| func (m *VendorExtension) ToRawInfo() interface{} { | func (m *VendorExtension) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.AdditionalProperties != nil { | 	if m.AdditionalProperties != nil { | ||||||
| 		for _, item := range m.AdditionalProperties { | 		for _, item := range m.AdditionalProperties { | ||||||
| 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | 			info = append(info, yaml.MapItem{Key: item.Name, Value: item.Value.ToRawInfo()}) | ||||||
|  | @ -8697,6 +8813,9 @@ func (m *VendorExtension) ToRawInfo() interface{} { | ||||||
| // ToRawInfo returns a description of Xml suitable for JSON or YAML export.
 | // ToRawInfo returns a description of Xml suitable for JSON or YAML export.
 | ||||||
| func (m *Xml) ToRawInfo() interface{} { | func (m *Xml) ToRawInfo() interface{} { | ||||||
| 	info := yaml.MapSlice{} | 	info := yaml.MapSlice{} | ||||||
|  | 	if m == nil { | ||||||
|  | 		return info | ||||||
|  | 	} | ||||||
| 	if m.Name != "" { | 	if m.Name != "" { | ||||||
| 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | 		info = append(info, yaml.MapItem{Key: "name", Value: m.Name}) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -17,13 +17,14 @@ package compiler | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"gopkg.in/yaml.v2" |  | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"log" | 	"log" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	yaml "gopkg.in/yaml.v2" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var fileCache map[string][]byte | var fileCache map[string][]byte | ||||||
|  | @ -31,6 +32,8 @@ var infoCache map[string]interface{} | ||||||
| var count int64 | var count int64 | ||||||
| 
 | 
 | ||||||
| var verboseReader = false | var verboseReader = false | ||||||
|  | var fileCacheEnable = true | ||||||
|  | var infoCacheEnable = true | ||||||
| 
 | 
 | ||||||
| func initializeFileCache() { | func initializeFileCache() { | ||||||
| 	if fileCache == nil { | 	if fileCache == nil { | ||||||
|  | @ -44,29 +47,67 @@ func initializeInfoCache() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func DisableFileCache() { | ||||||
|  | 	fileCacheEnable = false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func DisableInfoCache() { | ||||||
|  | 	infoCacheEnable = false | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func RemoveFromFileCache(fileurl string) { | ||||||
|  | 	if !fileCacheEnable { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	initializeFileCache() | ||||||
|  | 	delete(fileCache, fileurl) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func RemoveFromInfoCache(filename string) { | ||||||
|  | 	if !infoCacheEnable { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	initializeInfoCache() | ||||||
|  | 	delete(infoCache, filename) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func GetInfoCache() map[string]interface{} { | ||||||
|  | 	if infoCache == nil { | ||||||
|  | 		initializeInfoCache() | ||||||
|  | 	} | ||||||
|  | 	return infoCache | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func ClearInfoCache() { | ||||||
|  | 	infoCache = make(map[string]interface{}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // FetchFile gets a specified file from the local filesystem or a remote location.
 | // FetchFile gets a specified file from the local filesystem or a remote location.
 | ||||||
| func FetchFile(fileurl string) ([]byte, error) { | func FetchFile(fileurl string) ([]byte, error) { | ||||||
|  | 	var bytes []byte | ||||||
| 	initializeFileCache() | 	initializeFileCache() | ||||||
| 	bytes, ok := fileCache[fileurl] | 	if fileCacheEnable { | ||||||
| 	if ok { | 		bytes, ok := fileCache[fileurl] | ||||||
| 		if verboseReader { | 		if ok { | ||||||
| 			log.Printf("Cache hit %s", fileurl) | 			if verboseReader { | ||||||
|  | 				log.Printf("Cache hit %s", fileurl) | ||||||
|  | 			} | ||||||
|  | 			return bytes, nil | ||||||
|  | 		} | ||||||
|  | 		if verboseReader { | ||||||
|  | 			log.Printf("Fetching %s", fileurl) | ||||||
| 		} | 		} | ||||||
| 		return bytes, nil |  | ||||||
| 	} |  | ||||||
| 	if verboseReader { |  | ||||||
| 		log.Printf("Fetching %s", fileurl) |  | ||||||
| 	} | 	} | ||||||
| 	response, err := http.Get(fileurl) | 	response, err := http.Get(fileurl) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | 	defer response.Body.Close() | ||||||
| 	if response.StatusCode != 200 { | 	if response.StatusCode != 200 { | ||||||
| 		return nil, errors.New(fmt.Sprintf("Error downloading %s: %s", fileurl, response.Status)) | 		return nil, errors.New(fmt.Sprintf("Error downloading %s: %s", fileurl, response.Status)) | ||||||
| 	} | 	} | ||||||
| 	defer response.Body.Close() |  | ||||||
| 	bytes, err = ioutil.ReadAll(response.Body) | 	bytes, err = ioutil.ReadAll(response.Body) | ||||||
| 	if err == nil { | 	if fileCacheEnable && err == nil { | ||||||
| 		fileCache[fileurl] = bytes | 		fileCache[fileurl] = bytes | ||||||
| 	} | 	} | ||||||
| 	return bytes, err | 	return bytes, err | ||||||
|  | @ -95,22 +136,24 @@ func ReadBytesForFile(filename string) ([]byte, error) { | ||||||
| // ReadInfoFromBytes unmarshals a file as a yaml.MapSlice.
 | // ReadInfoFromBytes unmarshals a file as a yaml.MapSlice.
 | ||||||
| func ReadInfoFromBytes(filename string, bytes []byte) (interface{}, error) { | func ReadInfoFromBytes(filename string, bytes []byte) (interface{}, error) { | ||||||
| 	initializeInfoCache() | 	initializeInfoCache() | ||||||
| 	cachedInfo, ok := infoCache[filename] | 	if infoCacheEnable { | ||||||
| 	if ok { | 		cachedInfo, ok := infoCache[filename] | ||||||
| 		if verboseReader { | 		if ok { | ||||||
| 			log.Printf("Cache hit info for file %s", filename) | 			if verboseReader { | ||||||
|  | 				log.Printf("Cache hit info for file %s", filename) | ||||||
|  | 			} | ||||||
|  | 			return cachedInfo, nil | ||||||
|  | 		} | ||||||
|  | 		if verboseReader { | ||||||
|  | 			log.Printf("Reading info for file %s", filename) | ||||||
| 		} | 		} | ||||||
| 		return cachedInfo, nil |  | ||||||
| 	} |  | ||||||
| 	if verboseReader { |  | ||||||
| 		log.Printf("Reading info for file %s", filename) |  | ||||||
| 	} | 	} | ||||||
| 	var info yaml.MapSlice | 	var info yaml.MapSlice | ||||||
| 	err := yaml.Unmarshal(bytes, &info) | 	err := yaml.Unmarshal(bytes, &info) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	if len(filename) > 0 { | 	if infoCacheEnable && len(filename) > 0 { | ||||||
| 		infoCache[filename] = info | 		infoCache[filename] = info | ||||||
| 	} | 	} | ||||||
| 	return info, nil | 	return info, nil | ||||||
|  | @ -119,7 +162,7 @@ func ReadInfoFromBytes(filename string, bytes []byte) (interface{}, error) { | ||||||
| // ReadInfoForRef reads a file and return the fragment needed to resolve a $ref.
 | // ReadInfoForRef reads a file and return the fragment needed to resolve a $ref.
 | ||||||
| func ReadInfoForRef(basefile string, ref string) (interface{}, error) { | func ReadInfoForRef(basefile string, ref string) (interface{}, error) { | ||||||
| 	initializeInfoCache() | 	initializeInfoCache() | ||||||
| 	{ | 	if infoCacheEnable { | ||||||
| 		info, ok := infoCache[ref] | 		info, ok := infoCache[ref] | ||||||
| 		if ok { | 		if ok { | ||||||
| 			if verboseReader { | 			if verboseReader { | ||||||
|  | @ -127,16 +170,20 @@ func ReadInfoForRef(basefile string, ref string) (interface{}, error) { | ||||||
| 			} | 			} | ||||||
| 			return info, nil | 			return info, nil | ||||||
| 		} | 		} | ||||||
| 	} | 		if verboseReader { | ||||||
| 	if verboseReader { | 			log.Printf("Reading info for ref %s#%s", basefile, ref) | ||||||
| 		log.Printf("Reading info for ref %s#%s", basefile, ref) | 		} | ||||||
| 	} | 	} | ||||||
| 	count = count + 1 | 	count = count + 1 | ||||||
| 	basedir, _ := filepath.Split(basefile) | 	basedir, _ := filepath.Split(basefile) | ||||||
| 	parts := strings.Split(ref, "#") | 	parts := strings.Split(ref, "#") | ||||||
| 	var filename string | 	var filename string | ||||||
| 	if parts[0] != "" { | 	if parts[0] != "" { | ||||||
| 		filename = basedir + parts[0] | 		filename = parts[0] | ||||||
|  | 		if _, err := url.ParseRequestURI(parts[0]); err != nil { | ||||||
|  | 			// It is not an URL, so the file is local
 | ||||||
|  | 			filename = basedir + parts[0] | ||||||
|  | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		filename = basefile | 		filename = basefile | ||||||
| 	} | 	} | ||||||
|  | @ -170,6 +217,8 @@ func ReadInfoForRef(basefile string, ref string) (interface{}, error) { | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	infoCache[ref] = info | 	if infoCacheEnable { | ||||||
|  | 		infoCache[ref] = info | ||||||
|  | 	} | ||||||
| 	return info, nil | 	return info, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,5 +0,0 @@ | ||||||
| go get github.com/golang/protobuf/protoc-gen-go |  | ||||||
| 
 |  | ||||||
| protoc \ |  | ||||||
| --go_out=Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. *.proto  |  | ||||||
| 
 |  | ||||||
|  | @ -1,24 +1,14 @@ | ||||||
| // Code generated by protoc-gen-go. DO NOT EDIT.
 | // Code generated by protoc-gen-go. DO NOT EDIT.
 | ||||||
| // source: extension.proto
 | // source: extensions/extension.proto
 | ||||||
| 
 | 
 | ||||||
| /* |  | ||||||
| Package openapiextension_v1 is a generated protocol buffer package. |  | ||||||
| 
 |  | ||||||
| It is generated from these files: |  | ||||||
| 	extension.proto |  | ||||||
| 
 |  | ||||||
| It has these top-level messages: |  | ||||||
| 	Version |  | ||||||
| 	ExtensionHandlerRequest |  | ||||||
| 	ExtensionHandlerResponse |  | ||||||
| 	Wrapper |  | ||||||
| */ |  | ||||||
| package openapiextension_v1 | package openapiextension_v1 | ||||||
| 
 | 
 | ||||||
| import proto "github.com/golang/protobuf/proto" | import ( | ||||||
| import fmt "fmt" | 	fmt "fmt" | ||||||
| import math "math" | 	proto "github.com/golang/protobuf/proto" | ||||||
| import google_protobuf "github.com/golang/protobuf/ptypes/any" | 	any "github.com/golang/protobuf/ptypes/any" | ||||||
|  | 	math "math" | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| // Reference imports to suppress errors if they are not otherwise used.
 | // Reference imports to suppress errors if they are not otherwise used.
 | ||||||
| var _ = proto.Marshal | var _ = proto.Marshal | ||||||
|  | @ -29,22 +19,45 @@ var _ = math.Inf | ||||||
| // is compatible with the proto package it is being compiled against.
 | // is compatible with the proto package it is being compiled against.
 | ||||||
| // A compilation error at this line likely means your copy of the
 | // A compilation error at this line likely means your copy of the
 | ||||||
| // proto package needs to be updated.
 | // proto package needs to be updated.
 | ||||||
| const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
 | ||||||
| 
 | 
 | ||||||
| // The version number of OpenAPI compiler.
 | // The version number of OpenAPI compiler.
 | ||||||
| type Version struct { | type Version struct { | ||||||
| 	Major int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"` | 	Major int32 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"` | ||||||
| 	Minor int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"` | 	Minor int32 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,omitempty"` | ||||||
| 	Patch int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"` | 	Patch int32 `protobuf:"varint,3,opt,name=patch,proto3" json:"patch,omitempty"` | ||||||
| 	// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
 | 	// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
 | ||||||
| 	// be empty for mainline stable releases.
 | 	// be empty for mainline stable releases.
 | ||||||
| 	Suffix string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"` | 	Suffix               string   `protobuf:"bytes,4,opt,name=suffix,proto3" json:"suffix,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *Version) Reset()                    { *m = Version{} } | func (m *Version) Reset()         { *m = Version{} } | ||||||
| func (m *Version) String() string            { return proto.CompactTextString(m) } | func (m *Version) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Version) ProtoMessage()               {} | func (*Version) ProtoMessage()    {} | ||||||
| func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } | func (*Version) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_661e47e790f76671, []int{0} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m *Version) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Version.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Version.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Version) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Version.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Version) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Version.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Version) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Version.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var xxx_messageInfo_Version proto.InternalMessageInfo | ||||||
| 
 | 
 | ||||||
| func (m *Version) GetMajor() int32 { | func (m *Version) GetMajor() int32 { | ||||||
| 	if m != nil { | 	if m != nil { | ||||||
|  | @ -78,15 +91,38 @@ func (m *Version) GetSuffix() string { | ||||||
| type ExtensionHandlerRequest struct { | type ExtensionHandlerRequest struct { | ||||||
| 	// The OpenAPI descriptions that were explicitly listed on the command line.
 | 	// The OpenAPI descriptions that were explicitly listed on the command line.
 | ||||||
| 	// The specifications will appear in the order they are specified to gnostic.
 | 	// The specifications will appear in the order they are specified to gnostic.
 | ||||||
| 	Wrapper *Wrapper `protobuf:"bytes,1,opt,name=wrapper" json:"wrapper,omitempty"` | 	Wrapper *Wrapper `protobuf:"bytes,1,opt,name=wrapper,proto3" json:"wrapper,omitempty"` | ||||||
| 	// The version number of openapi compiler.
 | 	// The version number of openapi compiler.
 | ||||||
| 	CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"` | 	CompilerVersion      *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion,proto3" json:"compiler_version,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *ExtensionHandlerRequest) Reset()                    { *m = ExtensionHandlerRequest{} } | func (m *ExtensionHandlerRequest) Reset()         { *m = ExtensionHandlerRequest{} } | ||||||
| func (m *ExtensionHandlerRequest) String() string            { return proto.CompactTextString(m) } | func (m *ExtensionHandlerRequest) String() string { return proto.CompactTextString(m) } | ||||||
| func (*ExtensionHandlerRequest) ProtoMessage()               {} | func (*ExtensionHandlerRequest) ProtoMessage()    {} | ||||||
| func (*ExtensionHandlerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } | func (*ExtensionHandlerRequest) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_661e47e790f76671, []int{1} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m *ExtensionHandlerRequest) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_ExtensionHandlerRequest.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *ExtensionHandlerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_ExtensionHandlerRequest.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *ExtensionHandlerRequest) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_ExtensionHandlerRequest.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *ExtensionHandlerRequest) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_ExtensionHandlerRequest.Size(m) | ||||||
|  | } | ||||||
|  | func (m *ExtensionHandlerRequest) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_ExtensionHandlerRequest.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var xxx_messageInfo_ExtensionHandlerRequest proto.InternalMessageInfo | ||||||
| 
 | 
 | ||||||
| func (m *ExtensionHandlerRequest) GetWrapper() *Wrapper { | func (m *ExtensionHandlerRequest) GetWrapper() *Wrapper { | ||||||
| 	if m != nil { | 	if m != nil { | ||||||
|  | @ -105,7 +141,7 @@ func (m *ExtensionHandlerRequest) GetCompilerVersion() *Version { | ||||||
| // The extensions writes an encoded ExtensionHandlerResponse to stdout.
 | // The extensions writes an encoded ExtensionHandlerResponse to stdout.
 | ||||||
| type ExtensionHandlerResponse struct { | type ExtensionHandlerResponse struct { | ||||||
| 	// true if the extension is handled by the extension handler; false otherwise
 | 	// true if the extension is handled by the extension handler; false otherwise
 | ||||||
| 	Handled bool `protobuf:"varint,1,opt,name=handled" json:"handled,omitempty"` | 	Handled bool `protobuf:"varint,1,opt,name=handled,proto3" json:"handled,omitempty"` | ||||||
| 	// Error message.  If non-empty, the extension handling failed.
 | 	// Error message.  If non-empty, the extension handling failed.
 | ||||||
| 	// The extension handler process should exit with status code zero
 | 	// The extension handler process should exit with status code zero
 | ||||||
| 	// even if it reports an error in this way.
 | 	// even if it reports an error in this way.
 | ||||||
|  | @ -115,15 +151,38 @@ type ExtensionHandlerResponse struct { | ||||||
| 	// itself -- such as the input Document being unparseable -- should be
 | 	// itself -- such as the input Document being unparseable -- should be
 | ||||||
| 	// reported by writing a message to stderr and exiting with a non-zero
 | 	// reported by writing a message to stderr and exiting with a non-zero
 | ||||||
| 	// status code.
 | 	// status code.
 | ||||||
| 	Error []string `protobuf:"bytes,2,rep,name=error" json:"error,omitempty"` | 	Error []string `protobuf:"bytes,2,rep,name=error,proto3" json:"error,omitempty"` | ||||||
| 	// text output
 | 	// text output
 | ||||||
| 	Value *google_protobuf.Any `protobuf:"bytes,3,opt,name=value" json:"value,omitempty"` | 	Value                *any.Any `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *ExtensionHandlerResponse) Reset()                    { *m = ExtensionHandlerResponse{} } | func (m *ExtensionHandlerResponse) Reset()         { *m = ExtensionHandlerResponse{} } | ||||||
| func (m *ExtensionHandlerResponse) String() string            { return proto.CompactTextString(m) } | func (m *ExtensionHandlerResponse) String() string { return proto.CompactTextString(m) } | ||||||
| func (*ExtensionHandlerResponse) ProtoMessage()               {} | func (*ExtensionHandlerResponse) ProtoMessage()    {} | ||||||
| func (*ExtensionHandlerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } | func (*ExtensionHandlerResponse) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_661e47e790f76671, []int{2} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m *ExtensionHandlerResponse) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_ExtensionHandlerResponse.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *ExtensionHandlerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_ExtensionHandlerResponse.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *ExtensionHandlerResponse) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_ExtensionHandlerResponse.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *ExtensionHandlerResponse) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_ExtensionHandlerResponse.Size(m) | ||||||
|  | } | ||||||
|  | func (m *ExtensionHandlerResponse) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_ExtensionHandlerResponse.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var xxx_messageInfo_ExtensionHandlerResponse proto.InternalMessageInfo | ||||||
| 
 | 
 | ||||||
| func (m *ExtensionHandlerResponse) GetHandled() bool { | func (m *ExtensionHandlerResponse) GetHandled() bool { | ||||||
| 	if m != nil { | 	if m != nil { | ||||||
|  | @ -139,7 +198,7 @@ func (m *ExtensionHandlerResponse) GetError() []string { | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *ExtensionHandlerResponse) GetValue() *google_protobuf.Any { | func (m *ExtensionHandlerResponse) GetValue() *any.Any { | ||||||
| 	if m != nil { | 	if m != nil { | ||||||
| 		return m.Value | 		return m.Value | ||||||
| 	} | 	} | ||||||
|  | @ -148,17 +207,40 @@ func (m *ExtensionHandlerResponse) GetValue() *google_protobuf.Any { | ||||||
| 
 | 
 | ||||||
| type Wrapper struct { | type Wrapper struct { | ||||||
| 	// version of the OpenAPI specification in which this extension was written.
 | 	// version of the OpenAPI specification in which this extension was written.
 | ||||||
| 	Version string `protobuf:"bytes,1,opt,name=version" json:"version,omitempty"` | 	Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` | ||||||
| 	// Name of the extension
 | 	// Name of the extension
 | ||||||
| 	ExtensionName string `protobuf:"bytes,2,opt,name=extension_name,json=extensionName" json:"extension_name,omitempty"` | 	ExtensionName string `protobuf:"bytes,2,opt,name=extension_name,json=extensionName,proto3" json:"extension_name,omitempty"` | ||||||
| 	// Must be a valid yaml for the proto
 | 	// Must be a valid yaml for the proto
 | ||||||
| 	Yaml string `protobuf:"bytes,3,opt,name=yaml" json:"yaml,omitempty"` | 	Yaml                 string   `protobuf:"bytes,3,opt,name=yaml,proto3" json:"yaml,omitempty"` | ||||||
|  | 	XXX_NoUnkeyedLiteral struct{} `json:"-"` | ||||||
|  | 	XXX_unrecognized     []byte   `json:"-"` | ||||||
|  | 	XXX_sizecache        int32    `json:"-"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *Wrapper) Reset()                    { *m = Wrapper{} } | func (m *Wrapper) Reset()         { *m = Wrapper{} } | ||||||
| func (m *Wrapper) String() string            { return proto.CompactTextString(m) } | func (m *Wrapper) String() string { return proto.CompactTextString(m) } | ||||||
| func (*Wrapper) ProtoMessage()               {} | func (*Wrapper) ProtoMessage()    {} | ||||||
| func (*Wrapper) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } | func (*Wrapper) Descriptor() ([]byte, []int) { | ||||||
|  | 	return fileDescriptor_661e47e790f76671, []int{3} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (m *Wrapper) XXX_Unmarshal(b []byte) error { | ||||||
|  | 	return xxx_messageInfo_Wrapper.Unmarshal(m, b) | ||||||
|  | } | ||||||
|  | func (m *Wrapper) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { | ||||||
|  | 	return xxx_messageInfo_Wrapper.Marshal(b, m, deterministic) | ||||||
|  | } | ||||||
|  | func (m *Wrapper) XXX_Merge(src proto.Message) { | ||||||
|  | 	xxx_messageInfo_Wrapper.Merge(m, src) | ||||||
|  | } | ||||||
|  | func (m *Wrapper) XXX_Size() int { | ||||||
|  | 	return xxx_messageInfo_Wrapper.Size(m) | ||||||
|  | } | ||||||
|  | func (m *Wrapper) XXX_DiscardUnknown() { | ||||||
|  | 	xxx_messageInfo_Wrapper.DiscardUnknown(m) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var xxx_messageInfo_Wrapper proto.InternalMessageInfo | ||||||
| 
 | 
 | ||||||
| func (m *Wrapper) GetVersion() string { | func (m *Wrapper) GetVersion() string { | ||||||
| 	if m != nil { | 	if m != nil { | ||||||
|  | @ -188,31 +270,31 @@ func init() { | ||||||
| 	proto.RegisterType((*Wrapper)(nil), "openapiextension.v1.Wrapper") | 	proto.RegisterType((*Wrapper)(nil), "openapiextension.v1.Wrapper") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { proto.RegisterFile("extension.proto", fileDescriptor0) } | func init() { proto.RegisterFile("extensions/extension.proto", fileDescriptor_661e47e790f76671) } | ||||||
| 
 | 
 | ||||||
| var fileDescriptor0 = []byte{ | var fileDescriptor_661e47e790f76671 = []byte{ | ||||||
| 	// 357 bytes of a gzipped FileDescriptorProto
 | 	// 362 bytes of a gzipped FileDescriptorProto
 | ||||||
| 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x4d, 0x4b, 0xc3, 0x40, | 	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x4d, 0x4b, 0xeb, 0x40, | ||||||
| 	0x18, 0x84, 0x49, 0xbf, 0x62, 0x56, 0x6c, 0x65, 0x2d, 0x1a, 0xc5, 0x43, 0x09, 0x08, 0x45, 0x64, | 	0x18, 0x85, 0x49, 0xbf, 0x72, 0x33, 0x97, 0xdb, 0x2b, 0x63, 0xd1, 0x58, 0x5c, 0x94, 0x80, 0x50, | ||||||
| 	0x4b, 0x15, 0xbc, 0xb7, 0x50, 0xd4, 0x8b, 0x2d, 0x7b, 0xa8, 0x37, 0xcb, 0x36, 0x7d, 0x9b, 0x46, | 	0x44, 0xa6, 0x54, 0xc1, 0x7d, 0x0b, 0x45, 0xdd, 0xd8, 0x32, 0x8b, 0xba, 0xb3, 0x4c, 0xd3, 0xb7, | ||||||
| 	0x92, 0xdd, 0x75, 0xf3, 0x61, 0xfb, 0x57, 0x3c, 0xfa, 0x4b, 0x25, 0xbb, 0x49, 0x3d, 0xa8, 0xb7, | 	0x69, 0x24, 0x99, 0x19, 0x27, 0x1f, 0xb6, 0x7f, 0xc5, 0xa5, 0xbf, 0x54, 0x32, 0x93, 0xc4, 0x85, | ||||||
| 	0xcc, 0xc3, 0x24, 0xef, 0xcc, 0x04, 0x75, 0x60, 0x9b, 0x02, 0x4f, 0x42, 0xc1, 0x89, 0x54, 0x22, | 	0xba, 0x9b, 0xf3, 0x70, 0xda, 0xf7, 0x9c, 0x13, 0xd4, 0x87, 0x7d, 0x0a, 0x3c, 0x09, 0x05, 0x4f, | ||||||
| 	0x15, 0xf8, 0x44, 0x48, 0xe0, 0x4c, 0x86, 0x3f, 0x3c, 0x1f, 0x5e, 0x9c, 0x07, 0x42, 0x04, 0x11, | 	0x46, 0xf5, 0x93, 0x48, 0x25, 0x52, 0x81, 0x8f, 0x85, 0x04, 0xce, 0x64, 0xf8, 0xc5, 0xf3, 0x71, | ||||||
| 	0x0c, 0xb4, 0x65, 0x99, 0xad, 0x07, 0x8c, 0xef, 0x8c, 0xdf, 0xf3, 0x91, 0x3d, 0x07, 0x55, 0x18, | 	0xff, 0x2c, 0x10, 0x22, 0x88, 0x60, 0xa4, 0x2d, 0xeb, 0x6c, 0x3b, 0x62, 0xfc, 0x60, 0xfc, 0x9e, | ||||||
| 	0x71, 0x17, 0x35, 0x63, 0xf6, 0x26, 0x94, 0x6b, 0xf5, 0xac, 0x7e, 0x93, 0x1a, 0xa1, 0x69, 0xc8, | 	0x8f, 0xec, 0x25, 0xa8, 0xc2, 0x88, 0x7b, 0xa8, 0x1d, 0xb3, 0x17, 0xa1, 0x5c, 0x6b, 0x60, 0x0d, | ||||||
| 	0x85, 0x72, 0x6b, 0x25, 0x2d, 0x44, 0x41, 0x25, 0x4b, 0xfd, 0x8d, 0x5b, 0x37, 0x54, 0x0b, 0x7c, | 	0xdb, 0xd4, 0x08, 0x4d, 0x43, 0x2e, 0x94, 0xdb, 0x28, 0x69, 0x21, 0x0a, 0x2a, 0x59, 0xea, 0xef, | ||||||
| 	0x8a, 0x5a, 0x49, 0xb6, 0x5e, 0x87, 0x5b, 0xb7, 0xd1, 0xb3, 0xfa, 0x0e, 0x2d, 0x95, 0xf7, 0x69, | 	0xdc, 0xa6, 0xa1, 0x5a, 0xe0, 0x13, 0xd4, 0x49, 0xb2, 0xed, 0x36, 0xdc, 0xbb, 0xad, 0x81, 0x35, | ||||||
| 	0xa1, 0xb3, 0x49, 0x15, 0xe8, 0x91, 0xf1, 0x55, 0x04, 0x8a, 0xc2, 0x7b, 0x06, 0x49, 0x8a, 0xef, | 	0x74, 0x68, 0xa9, 0xbc, 0x77, 0x0b, 0x9d, 0xce, 0xaa, 0x40, 0xf7, 0x8c, 0x6f, 0x22, 0x50, 0x14, | ||||||
| 	0x91, 0xfd, 0xa1, 0x98, 0x94, 0x60, 0xee, 0x1e, 0xde, 0x5e, 0x92, 0x3f, 0x2a, 0x90, 0x17, 0xe3, | 	0x5e, 0x33, 0x48, 0x52, 0x7c, 0x8b, 0xec, 0x37, 0xc5, 0xa4, 0x04, 0x73, 0xf7, 0xef, 0xf5, 0x39, | ||||||
| 	0xa1, 0x95, 0x19, 0x3f, 0xa0, 0x63, 0x5f, 0xc4, 0x32, 0x8c, 0x40, 0x2d, 0x72, 0xd3, 0x40, 0x87, | 	0xf9, 0xa1, 0x02, 0x79, 0x32, 0x1e, 0x5a, 0x99, 0xf1, 0x1d, 0x3a, 0xf2, 0x45, 0x2c, 0xc3, 0x08, | ||||||
| 	0xf9, 0xef, 0x03, 0x65, 0x4b, 0xda, 0xa9, 0xde, 0x2a, 0x81, 0x97, 0x23, 0xf7, 0x77, 0xb6, 0x44, | 	0xd4, 0x2a, 0x37, 0x0d, 0x74, 0x98, 0xdf, 0xfe, 0xa0, 0x6c, 0x49, 0xff, 0x57, 0xbf, 0x2a, 0x81, | ||||||
| 	0x0a, 0x9e, 0x00, 0x76, 0x91, 0xbd, 0xd1, 0x68, 0xa5, 0xc3, 0x1d, 0xd0, 0x4a, 0x16, 0x03, 0x80, | 	0x97, 0x23, 0xf7, 0x7b, 0xb6, 0x44, 0x0a, 0x9e, 0x00, 0x76, 0x91, 0xbd, 0xd3, 0x68, 0xa3, 0xc3, | ||||||
| 	0x52, 0x7a, 0x96, 0x7a, 0xdf, 0xa1, 0x46, 0xe0, 0x6b, 0xd4, 0xcc, 0x59, 0x94, 0x41, 0x99, 0xa4, | 	0xfd, 0xa1, 0x95, 0x2c, 0x06, 0x00, 0xa5, 0xf4, 0x2c, 0xcd, 0xa1, 0x43, 0x8d, 0xc0, 0x97, 0xa8, | ||||||
| 	0x4b, 0xcc, 0xf0, 0xa4, 0x1a, 0x9e, 0x8c, 0xf8, 0x8e, 0x1a, 0x8b, 0xf7, 0x8a, 0xec, 0xb2, 0x54, | 	0x9d, 0xb3, 0x28, 0x83, 0x32, 0x49, 0x8f, 0x98, 0xe1, 0x49, 0x35, 0x3c, 0x99, 0xf0, 0x03, 0x35, | ||||||
| 	0x71, 0xa6, 0xaa, 0x60, 0xe9, 0xe1, 0x2a, 0x89, 0xaf, 0x50, 0x7b, 0xdf, 0x62, 0xc1, 0x59, 0x0c, | 	0x16, 0xef, 0x19, 0xd9, 0x65, 0xa9, 0xe2, 0x4c, 0x55, 0xc1, 0xd2, 0xc3, 0x55, 0x12, 0x5f, 0xa0, | ||||||
| 	0xfa, 0x37, 0x38, 0xf4, 0x68, 0x4f, 0x9f, 0x59, 0x0c, 0x18, 0xa3, 0xc6, 0x8e, 0xc5, 0x91, 0x3e, | 	0x6e, 0xdd, 0x62, 0xc5, 0x59, 0x0c, 0xfa, 0x33, 0x38, 0xf4, 0x5f, 0x4d, 0x1f, 0x59, 0x0c, 0x18, | ||||||
| 	0xeb, 0x50, 0xfd, 0x3c, 0xbe, 0x41, 0x6d, 0xa1, 0x02, 0x12, 0x70, 0x91, 0xa4, 0xa1, 0x4f, 0xf2, | 	0xa3, 0xd6, 0x81, 0xc5, 0x91, 0x3e, 0xeb, 0x50, 0xfd, 0x9e, 0x5e, 0xa1, 0xae, 0x50, 0x01, 0x09, | ||||||
| 	0xe1, 0x18, 0x4f, 0x25, 0xf0, 0xd1, 0xec, 0x69, 0x5f, 0x77, 0x3e, 0x9c, 0x59, 0x5f, 0xb5, 0xfa, | 	0xb8, 0x48, 0xd2, 0xd0, 0x27, 0xf9, 0x78, 0x8a, 0xe7, 0x12, 0xf8, 0x64, 0xf1, 0x50, 0xd7, 0x5d, | ||||||
| 	0x74, 0x34, 0x59, 0xb6, 0x74, 0xc4, 0xbb, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x84, 0x5c, 0x6b, | 	0x8e, 0x17, 0xd6, 0x47, 0xa3, 0x39, 0x9f, 0xcc, 0xd6, 0x1d, 0x1d, 0xf1, 0xe6, 0x33, 0x00, 0x00, | ||||||
| 	0x80, 0x51, 0x02, 0x00, 0x00, | 	0xff, 0xff, 0xeb, 0xf3, 0xfa, 0x65, 0x5c, 0x02, 0x00, 0x00, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -121,18 +121,18 @@ TEXT ·ladderstep(SB),0,$296-8 | ||||||
| 	ADDQ AX,R12 | 	ADDQ AX,R12 | ||||||
| 	ADCQ DX,R13 | 	ADCQ DX,R13 | ||||||
| 	MOVQ $REDMASK51,DX | 	MOVQ $REDMASK51,DX | ||||||
| 	SHLQ $13,CX:SI | 	SHLQ $13,SI,CX | ||||||
| 	ANDQ DX,SI | 	ANDQ DX,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ DX,R8 | 	ANDQ DX,R8 | ||||||
| 	ADDQ CX,R8 | 	ADDQ CX,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ DX,R10 | 	ANDQ DX,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ DX,R12 | 	ANDQ DX,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ DX,R14 | 	ANDQ DX,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	IMUL3Q $19,R15,CX | 	IMUL3Q $19,R15,CX | ||||||
|  | @ -236,18 +236,18 @@ TEXT ·ladderstep(SB),0,$296-8 | ||||||
| 	ADDQ AX,R12 | 	ADDQ AX,R12 | ||||||
| 	ADCQ DX,R13 | 	ADCQ DX,R13 | ||||||
| 	MOVQ $REDMASK51,DX | 	MOVQ $REDMASK51,DX | ||||||
| 	SHLQ $13,CX:SI | 	SHLQ $13,SI,CX | ||||||
| 	ANDQ DX,SI | 	ANDQ DX,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ DX,R8 | 	ANDQ DX,R8 | ||||||
| 	ADDQ CX,R8 | 	ADDQ CX,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ DX,R10 | 	ANDQ DX,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ DX,R12 | 	ANDQ DX,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ DX,R14 | 	ANDQ DX,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	IMUL3Q $19,R15,CX | 	IMUL3Q $19,R15,CX | ||||||
|  | @ -441,18 +441,18 @@ TEXT ·ladderstep(SB),0,$296-8 | ||||||
| 	ADDQ AX,R12 | 	ADDQ AX,R12 | ||||||
| 	ADCQ DX,R13 | 	ADCQ DX,R13 | ||||||
| 	MOVQ $REDMASK51,DX | 	MOVQ $REDMASK51,DX | ||||||
| 	SHLQ $13,CX:SI | 	SHLQ $13,SI,CX | ||||||
| 	ANDQ DX,SI | 	ANDQ DX,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ DX,R8 | 	ANDQ DX,R8 | ||||||
| 	ADDQ CX,R8 | 	ADDQ CX,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ DX,R10 | 	ANDQ DX,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ DX,R12 | 	ANDQ DX,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ DX,R14 | 	ANDQ DX,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	IMUL3Q $19,R15,CX | 	IMUL3Q $19,R15,CX | ||||||
|  | @ -591,18 +591,18 @@ TEXT ·ladderstep(SB),0,$296-8 | ||||||
| 	ADDQ AX,R12 | 	ADDQ AX,R12 | ||||||
| 	ADCQ DX,R13 | 	ADCQ DX,R13 | ||||||
| 	MOVQ $REDMASK51,DX | 	MOVQ $REDMASK51,DX | ||||||
| 	SHLQ $13,CX:SI | 	SHLQ $13,SI,CX | ||||||
| 	ANDQ DX,SI | 	ANDQ DX,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ DX,R8 | 	ANDQ DX,R8 | ||||||
| 	ADDQ CX,R8 | 	ADDQ CX,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ DX,R10 | 	ANDQ DX,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ DX,R12 | 	ANDQ DX,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ DX,R14 | 	ANDQ DX,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	IMUL3Q $19,R15,CX | 	IMUL3Q $19,R15,CX | ||||||
|  | @ -731,18 +731,18 @@ TEXT ·ladderstep(SB),0,$296-8 | ||||||
| 	ADDQ AX,R12 | 	ADDQ AX,R12 | ||||||
| 	ADCQ DX,R13 | 	ADCQ DX,R13 | ||||||
| 	MOVQ $REDMASK51,DX | 	MOVQ $REDMASK51,DX | ||||||
| 	SHLQ $13,CX:SI | 	SHLQ $13,SI,CX | ||||||
| 	ANDQ DX,SI | 	ANDQ DX,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ DX,R8 | 	ANDQ DX,R8 | ||||||
| 	ADDQ CX,R8 | 	ADDQ CX,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ DX,R10 | 	ANDQ DX,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ DX,R12 | 	ANDQ DX,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ DX,R14 | 	ANDQ DX,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	IMUL3Q $19,R15,CX | 	IMUL3Q $19,R15,CX | ||||||
|  | @ -846,18 +846,18 @@ TEXT ·ladderstep(SB),0,$296-8 | ||||||
| 	ADDQ AX,R12 | 	ADDQ AX,R12 | ||||||
| 	ADCQ DX,R13 | 	ADCQ DX,R13 | ||||||
| 	MOVQ $REDMASK51,DX | 	MOVQ $REDMASK51,DX | ||||||
| 	SHLQ $13,CX:SI | 	SHLQ $13,SI,CX | ||||||
| 	ANDQ DX,SI | 	ANDQ DX,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ DX,R8 | 	ANDQ DX,R8 | ||||||
| 	ADDQ CX,R8 | 	ADDQ CX,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ DX,R10 | 	ANDQ DX,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ DX,R12 | 	ANDQ DX,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ DX,R14 | 	ANDQ DX,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	IMUL3Q $19,R15,CX | 	IMUL3Q $19,R15,CX | ||||||
|  | @ -996,18 +996,18 @@ TEXT ·ladderstep(SB),0,$296-8 | ||||||
| 	ADDQ AX,R12 | 	ADDQ AX,R12 | ||||||
| 	ADCQ DX,R13 | 	ADCQ DX,R13 | ||||||
| 	MOVQ $REDMASK51,DX | 	MOVQ $REDMASK51,DX | ||||||
| 	SHLQ $13,CX:SI | 	SHLQ $13,SI,CX | ||||||
| 	ANDQ DX,SI | 	ANDQ DX,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ DX,R8 | 	ANDQ DX,R8 | ||||||
| 	ADDQ CX,R8 | 	ADDQ CX,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ DX,R10 | 	ANDQ DX,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ DX,R12 | 	ANDQ DX,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ DX,R14 | 	ANDQ DX,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	IMUL3Q $19,R15,CX | 	IMUL3Q $19,R15,CX | ||||||
|  | @ -1146,18 +1146,18 @@ TEXT ·ladderstep(SB),0,$296-8 | ||||||
| 	ADDQ AX,R12 | 	ADDQ AX,R12 | ||||||
| 	ADCQ DX,R13 | 	ADCQ DX,R13 | ||||||
| 	MOVQ $REDMASK51,DX | 	MOVQ $REDMASK51,DX | ||||||
| 	SHLQ $13,CX:SI | 	SHLQ $13,SI,CX | ||||||
| 	ANDQ DX,SI | 	ANDQ DX,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ DX,R8 | 	ANDQ DX,R8 | ||||||
| 	ADDQ CX,R8 | 	ADDQ CX,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ DX,R10 | 	ANDQ DX,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ DX,R12 | 	ANDQ DX,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ DX,R14 | 	ANDQ DX,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	IMUL3Q $19,R15,CX | 	IMUL3Q $19,R15,CX | ||||||
|  | @ -1332,18 +1332,18 @@ TEXT ·ladderstep(SB),0,$296-8 | ||||||
| 	ADDQ AX,R12 | 	ADDQ AX,R12 | ||||||
| 	ADCQ DX,R13 | 	ADCQ DX,R13 | ||||||
| 	MOVQ $REDMASK51,DX | 	MOVQ $REDMASK51,DX | ||||||
| 	SHLQ $13,CX:SI | 	SHLQ $13,SI,CX | ||||||
| 	ANDQ DX,SI | 	ANDQ DX,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ DX,R8 | 	ANDQ DX,R8 | ||||||
| 	ADDQ CX,R8 | 	ADDQ CX,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ DX,R10 | 	ANDQ DX,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ DX,R12 | 	ANDQ DX,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ DX,R14 | 	ANDQ DX,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	IMUL3Q $19,R15,CX | 	IMUL3Q $19,R15,CX | ||||||
|  |  | ||||||
|  | @ -124,18 +124,18 @@ TEXT ·mul(SB),0,$16-24 | ||||||
| 	ADDQ AX,R14 | 	ADDQ AX,R14 | ||||||
| 	ADCQ DX,R15 | 	ADCQ DX,R15 | ||||||
| 	MOVQ $REDMASK51,SI | 	MOVQ $REDMASK51,SI | ||||||
| 	SHLQ $13,R9:R8 | 	SHLQ $13,R8,R9 | ||||||
| 	ANDQ SI,R8 | 	ANDQ SI,R8 | ||||||
| 	SHLQ $13,R11:R10 | 	SHLQ $13,R10,R11 | ||||||
| 	ANDQ SI,R10 | 	ANDQ SI,R10 | ||||||
| 	ADDQ R9,R10 | 	ADDQ R9,R10 | ||||||
| 	SHLQ $13,R13:R12 | 	SHLQ $13,R12,R13 | ||||||
| 	ANDQ SI,R12 | 	ANDQ SI,R12 | ||||||
| 	ADDQ R11,R12 | 	ADDQ R11,R12 | ||||||
| 	SHLQ $13,R15:R14 | 	SHLQ $13,R14,R15 | ||||||
| 	ANDQ SI,R14 | 	ANDQ SI,R14 | ||||||
| 	ADDQ R13,R14 | 	ADDQ R13,R14 | ||||||
| 	SHLQ $13,BP:BX | 	SHLQ $13,BX,BP | ||||||
| 	ANDQ SI,BX | 	ANDQ SI,BX | ||||||
| 	ADDQ R15,BX | 	ADDQ R15,BX | ||||||
| 	IMUL3Q $19,BP,DX | 	IMUL3Q $19,BP,DX | ||||||
|  |  | ||||||
|  | @ -87,18 +87,18 @@ TEXT ·square(SB),7,$0-16 | ||||||
| 	ADDQ AX,R13 | 	ADDQ AX,R13 | ||||||
| 	ADCQ DX,R14 | 	ADCQ DX,R14 | ||||||
| 	MOVQ $REDMASK51,SI | 	MOVQ $REDMASK51,SI | ||||||
| 	SHLQ $13,R8:CX | 	SHLQ $13,CX,R8 | ||||||
| 	ANDQ SI,CX | 	ANDQ SI,CX | ||||||
| 	SHLQ $13,R10:R9 | 	SHLQ $13,R9,R10 | ||||||
| 	ANDQ SI,R9 | 	ANDQ SI,R9 | ||||||
| 	ADDQ R8,R9 | 	ADDQ R8,R9 | ||||||
| 	SHLQ $13,R12:R11 | 	SHLQ $13,R11,R12 | ||||||
| 	ANDQ SI,R11 | 	ANDQ SI,R11 | ||||||
| 	ADDQ R10,R11 | 	ADDQ R10,R11 | ||||||
| 	SHLQ $13,R14:R13 | 	SHLQ $13,R13,R14 | ||||||
| 	ANDQ SI,R13 | 	ANDQ SI,R13 | ||||||
| 	ADDQ R12,R13 | 	ADDQ R12,R13 | ||||||
| 	SHLQ $13,BX:R15 | 	SHLQ $13,R15,BX | ||||||
| 	ANDQ SI,R15 | 	ANDQ SI,R15 | ||||||
| 	ADDQ R14,R15 | 	ADDQ R14,R15 | ||||||
| 	IMUL3Q $19,BX,DX | 	IMUL3Q $19,BX,DX | ||||||
|  |  | ||||||
|  | @ -4,9 +4,10 @@ go_library( | ||||||
|     name = "go_default_library", |     name = "go_default_library", | ||||||
|     srcs = [ |     srcs = [ | ||||||
|         "hsalsa20.go", |         "hsalsa20.go", | ||||||
|         "salsa2020_amd64.s", |  | ||||||
|         "salsa208.go", |         "salsa208.go", | ||||||
|         "salsa20_amd64.go", |         "salsa20_amd64.go", | ||||||
|  |         "salsa20_amd64.s", | ||||||
|  |         "salsa20_noasm.go", | ||||||
|         "salsa20_ref.go", |         "salsa20_ref.go", | ||||||
|     ], |     ], | ||||||
|     importmap = "k8s.io/kops/vendor/golang.org/x/crypto/salsa20/salsa", |     importmap = "k8s.io/kops/vendor/golang.org/x/crypto/salsa20/salsa", | ||||||
|  |  | ||||||
|  | @ -6,10 +6,9 @@ | ||||||
| 
 | 
 | ||||||
| package salsa | package salsa | ||||||
| 
 | 
 | ||||||
| // This function is implemented in salsa2020_amd64.s.
 |  | ||||||
| 
 |  | ||||||
| //go:noescape
 | //go:noescape
 | ||||||
| 
 | 
 | ||||||
|  | // salsa2020XORKeyStream is implemented in salsa20_amd64.s.
 | ||||||
| func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) | func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) | ||||||
| 
 | 
 | ||||||
| // XORKeyStream crypts bytes from in to out using the given key and counters.
 | // XORKeyStream crypts bytes from in to out using the given key and counters.
 | ||||||
|  |  | ||||||
|  | @ -99,30 +99,24 @@ TEXT ·salsa2020XORKeyStream(SB),0,$456-40 // frame = 424 + 32 byte alignment | ||||||
| 	MOVL  36 (SP),CX | 	MOVL  36 (SP),CX | ||||||
| 	MOVL DX,288(SP) | 	MOVL DX,288(SP) | ||||||
| 	MOVL CX,304(SP) | 	MOVL CX,304(SP) | ||||||
| 	ADDQ $1,DX |  | ||||||
| 	SHLQ $32,CX | 	SHLQ $32,CX | ||||||
| 	ADDQ CX,DX | 	ADDQ CX,DX | ||||||
|  | 	ADDQ $1,DX | ||||||
| 	MOVQ DX,CX | 	MOVQ DX,CX | ||||||
| 	SHRQ $32,CX | 	SHRQ $32,CX | ||||||
| 	MOVL DX, 292 (SP) | 	MOVL DX, 292 (SP) | ||||||
| 	MOVL CX, 308 (SP) | 	MOVL CX, 308 (SP) | ||||||
| 	ADDQ $1,DX | 	ADDQ $1,DX | ||||||
| 	SHLQ $32,CX |  | ||||||
| 	ADDQ CX,DX |  | ||||||
| 	MOVQ DX,CX | 	MOVQ DX,CX | ||||||
| 	SHRQ $32,CX | 	SHRQ $32,CX | ||||||
| 	MOVL DX, 296 (SP) | 	MOVL DX, 296 (SP) | ||||||
| 	MOVL CX, 312 (SP) | 	MOVL CX, 312 (SP) | ||||||
| 	ADDQ $1,DX | 	ADDQ $1,DX | ||||||
| 	SHLQ $32,CX |  | ||||||
| 	ADDQ CX,DX |  | ||||||
| 	MOVQ DX,CX | 	MOVQ DX,CX | ||||||
| 	SHRQ $32,CX | 	SHRQ $32,CX | ||||||
| 	MOVL DX, 300 (SP) | 	MOVL DX, 300 (SP) | ||||||
| 	MOVL CX, 316 (SP) | 	MOVL CX, 316 (SP) | ||||||
| 	ADDQ $1,DX | 	ADDQ $1,DX | ||||||
| 	SHLQ $32,CX |  | ||||||
| 	ADDQ CX,DX |  | ||||||
| 	MOVQ DX,CX | 	MOVQ DX,CX | ||||||
| 	SHRQ $32,CX | 	SHRQ $32,CX | ||||||
| 	MOVL DX,16(SP) | 	MOVL DX,16(SP) | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | // 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.
 | ||||||
|  | 
 | ||||||
|  | // +build !amd64 appengine gccgo
 | ||||||
|  | 
 | ||||||
|  | package salsa | ||||||
|  | 
 | ||||||
|  | // XORKeyStream crypts bytes from in to out using the given key and counters.
 | ||||||
|  | // In and out must overlap entirely or not at all. Counter
 | ||||||
|  | // contains the raw salsa20 counter bytes (both nonce and block counter).
 | ||||||
|  | func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { | ||||||
|  | 	genericXORKeyStream(out, in, counter, key) | ||||||
|  | } | ||||||
|  | @ -2,8 +2,6 @@ | ||||||
| // Use of this source code is governed by a BSD-style
 | // Use of this source code is governed by a BSD-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
| // +build !amd64 appengine gccgo
 |  | ||||||
| 
 |  | ||||||
| package salsa | package salsa | ||||||
| 
 | 
 | ||||||
| const rounds = 20 | const rounds = 20 | ||||||
|  | @ -202,10 +200,9 @@ func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) { | ||||||
| 	out[63] = byte(x15 >> 24) | 	out[63] = byte(x15 >> 24) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // XORKeyStream crypts bytes from in to out using the given key and counters.
 | // genericXORKeyStream is the generic implementation of XORKeyStream to be used
 | ||||||
| // In and out must overlap entirely or not at all. Counter
 | // when no assembly implementation is available.
 | ||||||
| // contains the raw salsa20 counter bytes (both nonce and block counter).
 | func genericXORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { | ||||||
| func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { |  | ||||||
| 	var block [64]byte | 	var block [64]byte | ||||||
| 	var counterCopy [16]byte | 	var counterCopy [16]byte | ||||||
| 	copy(counterCopy[:], counter[:]) | 	copy(counterCopy[:], counter[:]) | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ package scrypt // import "golang.org/x/crypto/scrypt" | ||||||
| import ( | import ( | ||||||
| 	"crypto/sha256" | 	"crypto/sha256" | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"math/bits" | ||||||
| 
 | 
 | ||||||
| 	"golang.org/x/crypto/pbkdf2" | 	"golang.org/x/crypto/pbkdf2" | ||||||
| ) | ) | ||||||
|  | @ -52,77 +53,45 @@ func salsaXOR(tmp *[16]uint32, in, out []uint32) { | ||||||
| 	x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15 | 	x9, x10, x11, x12, x13, x14, x15 := w9, w10, w11, w12, w13, w14, w15 | ||||||
| 
 | 
 | ||||||
| 	for i := 0; i < 8; i += 2 { | 	for i := 0; i < 8; i += 2 { | ||||||
| 		u := x0 + x12 | 		x4 ^= bits.RotateLeft32(x0+x12, 7) | ||||||
| 		x4 ^= u<<7 | u>>(32-7) | 		x8 ^= bits.RotateLeft32(x4+x0, 9) | ||||||
| 		u = x4 + x0 | 		x12 ^= bits.RotateLeft32(x8+x4, 13) | ||||||
| 		x8 ^= u<<9 | u>>(32-9) | 		x0 ^= bits.RotateLeft32(x12+x8, 18) | ||||||
| 		u = x8 + x4 |  | ||||||
| 		x12 ^= u<<13 | u>>(32-13) |  | ||||||
| 		u = x12 + x8 |  | ||||||
| 		x0 ^= u<<18 | u>>(32-18) |  | ||||||
| 
 | 
 | ||||||
| 		u = x5 + x1 | 		x9 ^= bits.RotateLeft32(x5+x1, 7) | ||||||
| 		x9 ^= u<<7 | u>>(32-7) | 		x13 ^= bits.RotateLeft32(x9+x5, 9) | ||||||
| 		u = x9 + x5 | 		x1 ^= bits.RotateLeft32(x13+x9, 13) | ||||||
| 		x13 ^= u<<9 | u>>(32-9) | 		x5 ^= bits.RotateLeft32(x1+x13, 18) | ||||||
| 		u = x13 + x9 |  | ||||||
| 		x1 ^= u<<13 | u>>(32-13) |  | ||||||
| 		u = x1 + x13 |  | ||||||
| 		x5 ^= u<<18 | u>>(32-18) |  | ||||||
| 
 | 
 | ||||||
| 		u = x10 + x6 | 		x14 ^= bits.RotateLeft32(x10+x6, 7) | ||||||
| 		x14 ^= u<<7 | u>>(32-7) | 		x2 ^= bits.RotateLeft32(x14+x10, 9) | ||||||
| 		u = x14 + x10 | 		x6 ^= bits.RotateLeft32(x2+x14, 13) | ||||||
| 		x2 ^= u<<9 | u>>(32-9) | 		x10 ^= bits.RotateLeft32(x6+x2, 18) | ||||||
| 		u = x2 + x14 |  | ||||||
| 		x6 ^= u<<13 | u>>(32-13) |  | ||||||
| 		u = x6 + x2 |  | ||||||
| 		x10 ^= u<<18 | u>>(32-18) |  | ||||||
| 
 | 
 | ||||||
| 		u = x15 + x11 | 		x3 ^= bits.RotateLeft32(x15+x11, 7) | ||||||
| 		x3 ^= u<<7 | u>>(32-7) | 		x7 ^= bits.RotateLeft32(x3+x15, 9) | ||||||
| 		u = x3 + x15 | 		x11 ^= bits.RotateLeft32(x7+x3, 13) | ||||||
| 		x7 ^= u<<9 | u>>(32-9) | 		x15 ^= bits.RotateLeft32(x11+x7, 18) | ||||||
| 		u = x7 + x3 |  | ||||||
| 		x11 ^= u<<13 | u>>(32-13) |  | ||||||
| 		u = x11 + x7 |  | ||||||
| 		x15 ^= u<<18 | u>>(32-18) |  | ||||||
| 
 | 
 | ||||||
| 		u = x0 + x3 | 		x1 ^= bits.RotateLeft32(x0+x3, 7) | ||||||
| 		x1 ^= u<<7 | u>>(32-7) | 		x2 ^= bits.RotateLeft32(x1+x0, 9) | ||||||
| 		u = x1 + x0 | 		x3 ^= bits.RotateLeft32(x2+x1, 13) | ||||||
| 		x2 ^= u<<9 | u>>(32-9) | 		x0 ^= bits.RotateLeft32(x3+x2, 18) | ||||||
| 		u = x2 + x1 |  | ||||||
| 		x3 ^= u<<13 | u>>(32-13) |  | ||||||
| 		u = x3 + x2 |  | ||||||
| 		x0 ^= u<<18 | u>>(32-18) |  | ||||||
| 
 | 
 | ||||||
| 		u = x5 + x4 | 		x6 ^= bits.RotateLeft32(x5+x4, 7) | ||||||
| 		x6 ^= u<<7 | u>>(32-7) | 		x7 ^= bits.RotateLeft32(x6+x5, 9) | ||||||
| 		u = x6 + x5 | 		x4 ^= bits.RotateLeft32(x7+x6, 13) | ||||||
| 		x7 ^= u<<9 | u>>(32-9) | 		x5 ^= bits.RotateLeft32(x4+x7, 18) | ||||||
| 		u = x7 + x6 |  | ||||||
| 		x4 ^= u<<13 | u>>(32-13) |  | ||||||
| 		u = x4 + x7 |  | ||||||
| 		x5 ^= u<<18 | u>>(32-18) |  | ||||||
| 
 | 
 | ||||||
| 		u = x10 + x9 | 		x11 ^= bits.RotateLeft32(x10+x9, 7) | ||||||
| 		x11 ^= u<<7 | u>>(32-7) | 		x8 ^= bits.RotateLeft32(x11+x10, 9) | ||||||
| 		u = x11 + x10 | 		x9 ^= bits.RotateLeft32(x8+x11, 13) | ||||||
| 		x8 ^= u<<9 | u>>(32-9) | 		x10 ^= bits.RotateLeft32(x9+x8, 18) | ||||||
| 		u = x8 + x11 |  | ||||||
| 		x9 ^= u<<13 | u>>(32-13) |  | ||||||
| 		u = x9 + x8 |  | ||||||
| 		x10 ^= u<<18 | u>>(32-18) |  | ||||||
| 
 | 
 | ||||||
| 		u = x15 + x14 | 		x12 ^= bits.RotateLeft32(x15+x14, 7) | ||||||
| 		x12 ^= u<<7 | u>>(32-7) | 		x13 ^= bits.RotateLeft32(x12+x15, 9) | ||||||
| 		u = x12 + x15 | 		x14 ^= bits.RotateLeft32(x13+x12, 13) | ||||||
| 		x13 ^= u<<9 | u>>(32-9) | 		x15 ^= bits.RotateLeft32(x14+x13, 18) | ||||||
| 		u = x13 + x12 |  | ||||||
| 		x14 ^= u<<13 | u>>(32-13) |  | ||||||
| 		u = x14 + x13 |  | ||||||
| 		x15 ^= u<<18 | u>>(32-18) |  | ||||||
| 	} | 	} | ||||||
| 	x0 += w0 | 	x0 += w0 | ||||||
| 	x1 += w1 | 	x1 += w1 | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ go_library( | ||||||
|         "mux.go", |         "mux.go", | ||||||
|         "server.go", |         "server.go", | ||||||
|         "session.go", |         "session.go", | ||||||
|  |         "ssh_gss.go", | ||||||
|         "streamlocal.go", |         "streamlocal.go", | ||||||
|         "tcpip.go", |         "tcpip.go", | ||||||
|         "transport.go", |         "transport.go", | ||||||
|  |  | ||||||
|  | @ -149,8 +149,8 @@ type streamPacketCipher struct { | ||||||
| 	macResult   []byte | 	macResult   []byte | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // readPacket reads and decrypt a single packet from the reader argument.
 | // readCipherPacket reads and decrypt a single packet from the reader argument.
 | ||||||
| func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { | func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { | ||||||
| 	if _, err := io.ReadFull(r, s.prefix[:]); err != nil { | 	if _, err := io.ReadFull(r, s.prefix[:]); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -221,8 +221,8 @@ func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, err | ||||||
| 	return s.packetData[:length-paddingLength-1], nil | 	return s.packetData[:length-paddingLength-1], nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // writePacket encrypts and sends a packet of data to the writer argument
 | // writeCipherPacket encrypts and sends a packet of data to the writer argument
 | ||||||
| func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { | func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { | ||||||
| 	if len(packet) > maxPacket { | 	if len(packet) > maxPacket { | ||||||
| 		return errors.New("ssh: packet too large") | 		return errors.New("ssh: packet too large") | ||||||
| 	} | 	} | ||||||
|  | @ -327,7 +327,7 @@ func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms) | ||||||
| 
 | 
 | ||||||
| const gcmTagSize = 16 | const gcmTagSize = 16 | ||||||
| 
 | 
 | ||||||
| func (c *gcmCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { | func (c *gcmCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { | ||||||
| 	// Pad out to multiple of 16 bytes. This is different from the
 | 	// Pad out to multiple of 16 bytes. This is different from the
 | ||||||
| 	// stream cipher because that encrypts the length too.
 | 	// stream cipher because that encrypts the length too.
 | ||||||
| 	padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) | 	padding := byte(packetSizeMultiple - (1+len(packet))%packetSizeMultiple) | ||||||
|  | @ -370,7 +370,7 @@ func (c *gcmCipher) incIV() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *gcmCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { | func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { | ||||||
| 	if _, err := io.ReadFull(r, c.prefix[:]); err != nil { | 	if _, err := io.ReadFull(r, c.prefix[:]); err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  | @ -486,8 +486,8 @@ type cbcError string | ||||||
| 
 | 
 | ||||||
| func (e cbcError) Error() string { return string(e) } | func (e cbcError) Error() string { return string(e) } | ||||||
| 
 | 
 | ||||||
| func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { | func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { | ||||||
| 	p, err := c.readPacketLeaky(seqNum, r) | 	p, err := c.readCipherPacketLeaky(seqNum, r) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		if _, ok := err.(cbcError); ok { | 		if _, ok := err.(cbcError); ok { | ||||||
| 			// Verification error: read a fixed amount of
 | 			// Verification error: read a fixed amount of
 | ||||||
|  | @ -500,7 +500,7 @@ func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { | ||||||
| 	return p, err | 	return p, err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { | func (c *cbcCipher) readCipherPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) { | ||||||
| 	blockSize := c.decrypter.BlockSize() | 	blockSize := c.decrypter.BlockSize() | ||||||
| 
 | 
 | ||||||
| 	// Read the header, which will include some of the subsequent data in the
 | 	// Read the header, which will include some of the subsequent data in the
 | ||||||
|  | @ -576,7 +576,7 @@ func (c *cbcCipher) readPacketLeaky(seqNum uint32, r io.Reader) ([]byte, error) | ||||||
| 	return c.packetData[prefixLen:paddingStart], nil | 	return c.packetData[prefixLen:paddingStart], nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *cbcCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { | func (c *cbcCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error { | ||||||
| 	effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) | 	effectiveBlockSize := maxUInt32(cbcMinPacketSizeMultiple, c.encrypter.BlockSize()) | ||||||
| 
 | 
 | ||||||
| 	// Length of encrypted portion of the packet (header, payload, padding).
 | 	// Length of encrypted portion of the packet (header, payload, padding).
 | ||||||
|  | @ -665,7 +665,7 @@ func newChaCha20Cipher(key, unusedIV, unusedMACKey []byte, unusedAlgs directionA | ||||||
| 	return c, nil | 	return c, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) { | func (c *chacha20Poly1305Cipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) { | ||||||
| 	nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} | 	nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} | ||||||
| 	s := chacha20.New(c.contentKey, nonce) | 	s := chacha20.New(c.contentKey, nonce) | ||||||
| 	var polyKey [32]byte | 	var polyKey [32]byte | ||||||
|  | @ -723,7 +723,7 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte, | ||||||
| 	return plain, nil | 	return plain, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *chacha20Poly1305Cipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { | func (c *chacha20Poly1305Cipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, payload []byte) error { | ||||||
| 	nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} | 	nonce := [3]uint32{0, 0, bits.ReverseBytes32(seqNum)} | ||||||
| 	s := chacha20.New(c.contentKey, nonce) | 	s := chacha20.New(c.contentKey, nonce) | ||||||
| 	var polyKey [32]byte | 	var polyKey [32]byte | ||||||
|  |  | ||||||
|  | @ -523,3 +523,117 @@ func (r *retryableAuthMethod) method() string { | ||||||
| func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod { | func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod { | ||||||
| 	return &retryableAuthMethod{authMethod: auth, maxTries: maxTries} | 	return &retryableAuthMethod{authMethod: auth, maxTries: maxTries} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // GSSAPIWithMICAuthMethod is an AuthMethod with "gssapi-with-mic" authentication.
 | ||||||
|  | // See RFC 4462 section 3
 | ||||||
|  | // gssAPIClient is implementation of the GSSAPIClient interface, see the definition of the interface for details.
 | ||||||
|  | // target is the server host you want to log in to.
 | ||||||
|  | func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) AuthMethod { | ||||||
|  | 	if gssAPIClient == nil { | ||||||
|  | 		panic("gss-api client must be not nil with enable gssapi-with-mic") | ||||||
|  | 	} | ||||||
|  | 	return &gssAPIWithMICCallback{gssAPIClient: gssAPIClient, target: target} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type gssAPIWithMICCallback struct { | ||||||
|  | 	gssAPIClient GSSAPIClient | ||||||
|  | 	target       string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader) (authResult, []string, error) { | ||||||
|  | 	m := &userAuthRequestMsg{ | ||||||
|  | 		User:    user, | ||||||
|  | 		Service: serviceSSH, | ||||||
|  | 		Method:  g.method(), | ||||||
|  | 	} | ||||||
|  | 	// The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST.
 | ||||||
|  | 	// See RFC 4462 section 3.2.
 | ||||||
|  | 	m.Payload = appendU32(m.Payload, 1) | ||||||
|  | 	m.Payload = appendString(m.Payload, string(krb5OID)) | ||||||
|  | 	if err := c.writePacket(Marshal(m)); err != nil { | ||||||
|  | 		return authFailure, nil, err | ||||||
|  | 	} | ||||||
|  | 	// The server responds to the SSH_MSG_USERAUTH_REQUEST with either an
 | ||||||
|  | 	// SSH_MSG_USERAUTH_FAILURE if none of the mechanisms are supported or
 | ||||||
|  | 	// with an SSH_MSG_USERAUTH_GSSAPI_RESPONSE.
 | ||||||
|  | 	// See RFC 4462 section 3.3.
 | ||||||
|  | 	// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,so I don't want to check
 | ||||||
|  | 	// selected mech if it is valid.
 | ||||||
|  | 	packet, err := c.readPacket() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return authFailure, nil, err | ||||||
|  | 	} | ||||||
|  | 	userAuthGSSAPIResp := &userAuthGSSAPIResponse{} | ||||||
|  | 	if err := Unmarshal(packet, userAuthGSSAPIResp); err != nil { | ||||||
|  | 		return authFailure, nil, err | ||||||
|  | 	} | ||||||
|  | 	// Start the loop into the exchange token.
 | ||||||
|  | 	// See RFC 4462 section 3.4.
 | ||||||
|  | 	var token []byte | ||||||
|  | 	defer g.gssAPIClient.DeleteSecContext() | ||||||
|  | 	for { | ||||||
|  | 		// Initiates the establishment of a security context between the application and a remote peer.
 | ||||||
|  | 		nextToken, needContinue, err := g.gssAPIClient.InitSecContext("host@"+g.target, token, false) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return authFailure, nil, err | ||||||
|  | 		} | ||||||
|  | 		if len(nextToken) > 0 { | ||||||
|  | 			if err := c.writePacket(Marshal(&userAuthGSSAPIToken{ | ||||||
|  | 				Token: nextToken, | ||||||
|  | 			})); err != nil { | ||||||
|  | 				return authFailure, nil, err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if !needContinue { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		packet, err = c.readPacket() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return authFailure, nil, err | ||||||
|  | 		} | ||||||
|  | 		switch packet[0] { | ||||||
|  | 		case msgUserAuthFailure: | ||||||
|  | 			var msg userAuthFailureMsg | ||||||
|  | 			if err := Unmarshal(packet, &msg); err != nil { | ||||||
|  | 				return authFailure, nil, err | ||||||
|  | 			} | ||||||
|  | 			if msg.PartialSuccess { | ||||||
|  | 				return authPartialSuccess, msg.Methods, nil | ||||||
|  | 			} | ||||||
|  | 			return authFailure, msg.Methods, nil | ||||||
|  | 		case msgUserAuthGSSAPIError: | ||||||
|  | 			userAuthGSSAPIErrorResp := &userAuthGSSAPIError{} | ||||||
|  | 			if err := Unmarshal(packet, userAuthGSSAPIErrorResp); err != nil { | ||||||
|  | 				return authFailure, nil, err | ||||||
|  | 			} | ||||||
|  | 			return authFailure, nil, fmt.Errorf("GSS-API Error:\n"+ | ||||||
|  | 				"Major Status: %d\n"+ | ||||||
|  | 				"Minor Status: %d\n"+ | ||||||
|  | 				"Error Message: %s\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus, | ||||||
|  | 				userAuthGSSAPIErrorResp.Message) | ||||||
|  | 		case msgUserAuthGSSAPIToken: | ||||||
|  | 			userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} | ||||||
|  | 			if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { | ||||||
|  | 				return authFailure, nil, err | ||||||
|  | 			} | ||||||
|  | 			token = userAuthGSSAPITokenReq.Token | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// Binding Encryption Keys.
 | ||||||
|  | 	// See RFC 4462 section 3.5.
 | ||||||
|  | 	micField := buildMIC(string(session), user, "ssh-connection", "gssapi-with-mic") | ||||||
|  | 	micToken, err := g.gssAPIClient.GetMIC(micField) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return authFailure, nil, err | ||||||
|  | 	} | ||||||
|  | 	if err := c.writePacket(Marshal(&userAuthGSSAPIMIC{ | ||||||
|  | 		MIC: micToken, | ||||||
|  | 	})); err != nil { | ||||||
|  | 		return authFailure, nil, err | ||||||
|  | 	} | ||||||
|  | 	return handleAuthResponse(c) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (g *gssAPIWithMICCallback) method() string { | ||||||
|  | 	return "gssapi-with-mic" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -109,6 +109,7 @@ func findCommon(what string, client []string, server []string) (common string, e | ||||||
| 	return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) | 	return "", fmt.Errorf("ssh: no common algorithm for %s; client offered: %v, server offered: %v", what, client, server) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // directionAlgorithms records algorithm choices in one direction (either read or write)
 | ||||||
| type directionAlgorithms struct { | type directionAlgorithms struct { | ||||||
| 	Cipher      string | 	Cipher      string | ||||||
| 	MAC         string | 	MAC         string | ||||||
|  | @ -137,7 +138,7 @@ type algorithms struct { | ||||||
| 	r       directionAlgorithms | 	r       directionAlgorithms | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { | func findAgreedAlgorithms(isClient bool, clientKexInit, serverKexInit *kexInitMsg) (algs *algorithms, err error) { | ||||||
| 	result := &algorithms{} | 	result := &algorithms{} | ||||||
| 
 | 
 | ||||||
| 	result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) | 	result.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos) | ||||||
|  | @ -150,32 +151,37 @@ func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algor | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	result.w.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) | 	stoc, ctos := &result.w, &result.r | ||||||
|  | 	if isClient { | ||||||
|  | 		ctos, stoc = stoc, ctos | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ctos.Cipher, err = findCommon("client to server cipher", clientKexInit.CiphersClientServer, serverKexInit.CiphersClientServer) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	result.r.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) | 	stoc.Cipher, err = findCommon("server to client cipher", clientKexInit.CiphersServerClient, serverKexInit.CiphersServerClient) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	result.w.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) | 	ctos.MAC, err = findCommon("client to server MAC", clientKexInit.MACsClientServer, serverKexInit.MACsClientServer) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	result.r.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) | 	stoc.MAC, err = findCommon("server to client MAC", clientKexInit.MACsServerClient, serverKexInit.MACsServerClient) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	result.w.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) | 	ctos.Compression, err = findCommon("client to server compression", clientKexInit.CompressionClientServer, serverKexInit.CompressionClientServer) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	result.r.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) | 	stoc.Compression, err = findCommon("server to client compression", clientKexInit.CompressionServerClient, serverKexInit.CompressionServerClient) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -543,7 +543,8 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { | ||||||
| 
 | 
 | ||||||
| 	clientInit := otherInit | 	clientInit := otherInit | ||||||
| 	serverInit := t.sentInitMsg | 	serverInit := t.sentInitMsg | ||||||
| 	if len(t.hostKeys) == 0 { | 	isClient := len(t.hostKeys) == 0 | ||||||
|  | 	if isClient { | ||||||
| 		clientInit, serverInit = serverInit, clientInit | 		clientInit, serverInit = serverInit, clientInit | ||||||
| 
 | 
 | ||||||
| 		magics.clientKexInit = t.sentInitPacket | 		magics.clientKexInit = t.sentInitPacket | ||||||
|  | @ -551,7 +552,7 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var err error | 	var err error | ||||||
| 	t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit) | 	t.algorithms, err = findAgreedAlgorithms(isClient, clientInit, serverInit) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -275,6 +275,42 @@ type userAuthPubKeyOkMsg struct { | ||||||
| 	PubKey []byte | 	PubKey []byte | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // See RFC 4462, section 3
 | ||||||
|  | const msgUserAuthGSSAPIResponse = 60 | ||||||
|  | 
 | ||||||
|  | type userAuthGSSAPIResponse struct { | ||||||
|  | 	SupportMech []byte `sshtype:"60"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const msgUserAuthGSSAPIToken = 61 | ||||||
|  | 
 | ||||||
|  | type userAuthGSSAPIToken struct { | ||||||
|  | 	Token []byte `sshtype:"61"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const msgUserAuthGSSAPIMIC = 66 | ||||||
|  | 
 | ||||||
|  | type userAuthGSSAPIMIC struct { | ||||||
|  | 	MIC []byte `sshtype:"66"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // See RFC 4462, section 3.9
 | ||||||
|  | const msgUserAuthGSSAPIErrTok = 64 | ||||||
|  | 
 | ||||||
|  | type userAuthGSSAPIErrTok struct { | ||||||
|  | 	ErrorToken []byte `sshtype:"64"` | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // See RFC 4462, section 3.8
 | ||||||
|  | const msgUserAuthGSSAPIError = 65 | ||||||
|  | 
 | ||||||
|  | type userAuthGSSAPIError struct { | ||||||
|  | 	MajorStatus uint32 `sshtype:"65"` | ||||||
|  | 	MinorStatus uint32 | ||||||
|  | 	Message     string | ||||||
|  | 	LanguageTag string | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // typeTags returns the possible type bytes for the given reflect.Type, which
 | // typeTags returns the possible type bytes for the given reflect.Type, which
 | ||||||
| // should be a struct. The possible values are separated by a '|' character.
 | // should be a struct. The possible values are separated by a '|' character.
 | ||||||
| func typeTags(structType reflect.Type) (tags []byte) { | func typeTags(structType reflect.Type) (tags []byte) { | ||||||
|  | @ -756,6 +792,14 @@ func decode(packet []byte) (interface{}, error) { | ||||||
| 		msg = new(channelRequestSuccessMsg) | 		msg = new(channelRequestSuccessMsg) | ||||||
| 	case msgChannelFailure: | 	case msgChannelFailure: | ||||||
| 		msg = new(channelRequestFailureMsg) | 		msg = new(channelRequestFailureMsg) | ||||||
|  | 	case msgUserAuthGSSAPIToken: | ||||||
|  | 		msg = new(userAuthGSSAPIToken) | ||||||
|  | 	case msgUserAuthGSSAPIMIC: | ||||||
|  | 		msg = new(userAuthGSSAPIMIC) | ||||||
|  | 	case msgUserAuthGSSAPIErrTok: | ||||||
|  | 		msg = new(userAuthGSSAPIErrTok) | ||||||
|  | 	case msgUserAuthGSSAPIError: | ||||||
|  | 		msg = new(userAuthGSSAPIError) | ||||||
| 	default: | 	default: | ||||||
| 		return nil, unexpectedMessageError(0, packet[0]) | 		return nil, unexpectedMessageError(0, packet[0]) | ||||||
| 	} | 	} | ||||||
|  | @ -764,3 +808,29 @@ func decode(packet []byte) (interface{}, error) { | ||||||
| 	} | 	} | ||||||
| 	return msg, nil | 	return msg, nil | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | var packetTypeNames = map[byte]string{ | ||||||
|  | 	msgDisconnect:          "disconnectMsg", | ||||||
|  | 	msgServiceRequest:      "serviceRequestMsg", | ||||||
|  | 	msgServiceAccept:       "serviceAcceptMsg", | ||||||
|  | 	msgKexInit:             "kexInitMsg", | ||||||
|  | 	msgKexDHInit:           "kexDHInitMsg", | ||||||
|  | 	msgKexDHReply:          "kexDHReplyMsg", | ||||||
|  | 	msgUserAuthRequest:     "userAuthRequestMsg", | ||||||
|  | 	msgUserAuthSuccess:     "userAuthSuccessMsg", | ||||||
|  | 	msgUserAuthFailure:     "userAuthFailureMsg", | ||||||
|  | 	msgUserAuthPubKeyOk:    "userAuthPubKeyOkMsg", | ||||||
|  | 	msgGlobalRequest:       "globalRequestMsg", | ||||||
|  | 	msgRequestSuccess:      "globalRequestSuccessMsg", | ||||||
|  | 	msgRequestFailure:      "globalRequestFailureMsg", | ||||||
|  | 	msgChannelOpen:         "channelOpenMsg", | ||||||
|  | 	msgChannelData:         "channelDataMsg", | ||||||
|  | 	msgChannelOpenConfirm:  "channelOpenConfirmMsg", | ||||||
|  | 	msgChannelOpenFailure:  "channelOpenFailureMsg", | ||||||
|  | 	msgChannelWindowAdjust: "windowAdjustMsg", | ||||||
|  | 	msgChannelEOF:          "channelEOFMsg", | ||||||
|  | 	msgChannelClose:        "channelCloseMsg", | ||||||
|  | 	msgChannelRequest:      "channelRequestMsg", | ||||||
|  | 	msgChannelSuccess:      "channelRequestSuccessMsg", | ||||||
|  | 	msgChannelFailure:      "channelRequestFailureMsg", | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -45,6 +45,20 @@ type Permissions struct { | ||||||
| 	Extensions map[string]string | 	Extensions map[string]string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type GSSAPIWithMICConfig struct { | ||||||
|  | 	// AllowLogin, must be set, is called when gssapi-with-mic
 | ||||||
|  | 	// authentication is selected (RFC 4462 section 3). The srcName is from the
 | ||||||
|  | 	// results of the GSS-API authentication. The format is username@DOMAIN.
 | ||||||
|  | 	// GSSAPI just guarantees to the server who the user is, but not if they can log in, and with what permissions.
 | ||||||
|  | 	// This callback is called after the user identity is established with GSSAPI to decide if the user can login with
 | ||||||
|  | 	// which permissions. If the user is allowed to login, it should return a nil error.
 | ||||||
|  | 	AllowLogin func(conn ConnMetadata, srcName string) (*Permissions, error) | ||||||
|  | 
 | ||||||
|  | 	// Server must be set. It's the implementation
 | ||||||
|  | 	// of the GSSAPIServer interface. See GSSAPIServer interface for details.
 | ||||||
|  | 	Server GSSAPIServer | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // ServerConfig holds server specific configuration data.
 | // ServerConfig holds server specific configuration data.
 | ||||||
| type ServerConfig struct { | type ServerConfig struct { | ||||||
| 	// Config contains configuration shared between client and server.
 | 	// Config contains configuration shared between client and server.
 | ||||||
|  | @ -99,6 +113,10 @@ type ServerConfig struct { | ||||||
| 	// BannerCallback, if present, is called and the return string is sent to
 | 	// BannerCallback, if present, is called and the return string is sent to
 | ||||||
| 	// the client after key exchange completed but before authentication.
 | 	// the client after key exchange completed but before authentication.
 | ||||||
| 	BannerCallback func(conn ConnMetadata) string | 	BannerCallback func(conn ConnMetadata) string | ||||||
|  | 
 | ||||||
|  | 	// GSSAPIWithMICConfig includes gssapi server and callback, which if both non-nil, is used
 | ||||||
|  | 	// when gssapi-with-mic authentication is selected (RFC 4462 section 3).
 | ||||||
|  | 	GSSAPIWithMICConfig *GSSAPIWithMICConfig | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // AddHostKey adds a private key as a host key. If an existing host
 | // AddHostKey adds a private key as a host key. If an existing host
 | ||||||
|  | @ -204,7 +222,9 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) | ||||||
| 		return nil, errors.New("ssh: server has no host keys") | 		return nil, errors.New("ssh: server has no host keys") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && config.KeyboardInteractiveCallback == nil { | 	if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil && | ||||||
|  | 		config.KeyboardInteractiveCallback == nil && (config.GSSAPIWithMICConfig == nil || | ||||||
|  | 		config.GSSAPIWithMICConfig.AllowLogin == nil || config.GSSAPIWithMICConfig.Server == nil) { | ||||||
| 		return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") | 		return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -295,6 +315,55 @@ func checkSourceAddress(addr net.Addr, sourceAddrs string) error { | ||||||
| 	return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) | 	return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, firstToken []byte, s *connection, | ||||||
|  | 	sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) { | ||||||
|  | 	gssAPIServer := gssapiConfig.Server | ||||||
|  | 	defer gssAPIServer.DeleteSecContext() | ||||||
|  | 	var srcName string | ||||||
|  | 	for { | ||||||
|  | 		var ( | ||||||
|  | 			outToken     []byte | ||||||
|  | 			needContinue bool | ||||||
|  | 		) | ||||||
|  | 		outToken, srcName, needContinue, err = gssAPIServer.AcceptSecContext(firstToken) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err, nil, nil | ||||||
|  | 		} | ||||||
|  | 		if len(outToken) != 0 { | ||||||
|  | 			if err := s.transport.writePacket(Marshal(&userAuthGSSAPIToken{ | ||||||
|  | 				Token: outToken, | ||||||
|  | 			})); err != nil { | ||||||
|  | 				return nil, nil, err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if !needContinue { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 		packet, err := s.transport.readPacket() | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, nil, err | ||||||
|  | 		} | ||||||
|  | 		userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} | ||||||
|  | 		if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { | ||||||
|  | 			return nil, nil, err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	packet, err := s.transport.readPacket() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, nil, err | ||||||
|  | 	} | ||||||
|  | 	userAuthGSSAPIMICReq := &userAuthGSSAPIMIC{} | ||||||
|  | 	if err := Unmarshal(packet, userAuthGSSAPIMICReq); err != nil { | ||||||
|  | 		return nil, nil, err | ||||||
|  | 	} | ||||||
|  | 	mic := buildMIC(string(sessionID), userAuthReq.User, userAuthReq.Service, userAuthReq.Method) | ||||||
|  | 	if err := gssAPIServer.VerifyMIC(mic, userAuthGSSAPIMICReq.MIC); err != nil { | ||||||
|  | 		return err, nil, nil | ||||||
|  | 	} | ||||||
|  | 	perms, authErr = gssapiConfig.AllowLogin(s, srcName) | ||||||
|  | 	return authErr, perms, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // ServerAuthError represents server authentication errors and is
 | // ServerAuthError represents server authentication errors and is
 | ||||||
| // sometimes returned by NewServerConn. It appends any authentication
 | // sometimes returned by NewServerConn. It appends any authentication
 | ||||||
| // errors that may occur, and is returned if all of the authentication
 | // errors that may occur, and is returned if all of the authentication
 | ||||||
|  | @ -496,6 +565,49 @@ userAuthLoop: | ||||||
| 				authErr = candidate.result | 				authErr = candidate.result | ||||||
| 				perms = candidate.perms | 				perms = candidate.perms | ||||||
| 			} | 			} | ||||||
|  | 		case "gssapi-with-mic": | ||||||
|  | 			gssapiConfig := config.GSSAPIWithMICConfig | ||||||
|  | 			userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return nil, parseError(msgUserAuthRequest) | ||||||
|  | 			} | ||||||
|  | 			// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication.
 | ||||||
|  | 			if userAuthRequestGSSAPI.N == 0 { | ||||||
|  | 				authErr = fmt.Errorf("ssh: Mechanism negotiation is not supported") | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 			var i uint32 | ||||||
|  | 			present := false | ||||||
|  | 			for i = 0; i < userAuthRequestGSSAPI.N; i++ { | ||||||
|  | 				if userAuthRequestGSSAPI.OIDS[i].Equal(krb5Mesh) { | ||||||
|  | 					present = true | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if !present { | ||||||
|  | 				authErr = fmt.Errorf("ssh: GSSAPI authentication must use the Kerberos V5 mechanism") | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 			// Initial server response, see RFC 4462 section 3.3.
 | ||||||
|  | 			if err := s.transport.writePacket(Marshal(&userAuthGSSAPIResponse{ | ||||||
|  | 				SupportMech: krb5OID, | ||||||
|  | 			})); err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 			// Exchange token, see RFC 4462 section 3.4.
 | ||||||
|  | 			packet, err := s.transport.readPacket() | ||||||
|  | 			if err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 			userAuthGSSAPITokenReq := &userAuthGSSAPIToken{} | ||||||
|  | 			if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
|  | 			authErr, perms, err = gssExchangeToken(gssapiConfig, userAuthGSSAPITokenReq.Token, s, sessionID, | ||||||
|  | 				userAuthReq) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return nil, err | ||||||
|  | 			} | ||||||
| 		default: | 		default: | ||||||
| 			authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) | 			authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method) | ||||||
| 		} | 		} | ||||||
|  | @ -522,6 +634,10 @@ userAuthLoop: | ||||||
| 		if config.KeyboardInteractiveCallback != nil { | 		if config.KeyboardInteractiveCallback != nil { | ||||||
| 			failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") | 			failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive") | ||||||
| 		} | 		} | ||||||
|  | 		if config.GSSAPIWithMICConfig != nil && config.GSSAPIWithMICConfig.Server != nil && | ||||||
|  | 			config.GSSAPIWithMICConfig.AllowLogin != nil { | ||||||
|  | 			failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic") | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		if len(failureMsg.Methods) == 0 { | 		if len(failureMsg.Methods) == 0 { | ||||||
| 			return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") | 			return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false") | ||||||
|  |  | ||||||
|  | @ -0,0 +1,139 @@ | ||||||
|  | // Copyright 2011 The Go Authors. All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a BSD-style
 | ||||||
|  | // license that can be found in the LICENSE file.
 | ||||||
|  | 
 | ||||||
|  | package ssh | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"encoding/asn1" | ||||||
|  | 	"errors" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var krb5OID []byte | ||||||
|  | 
 | ||||||
|  | func init() { | ||||||
|  | 	krb5OID, _ = asn1.Marshal(krb5Mesh) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins.
 | ||||||
|  | type GSSAPIClient interface { | ||||||
|  | 	// InitSecContext initiates the establishment of a security context for GSS-API between the
 | ||||||
|  | 	// ssh client and ssh server. Initially the token parameter should be specified as nil.
 | ||||||
|  | 	// The routine may return a outputToken which should be transferred to
 | ||||||
|  | 	// the ssh server, where the ssh server will present it to
 | ||||||
|  | 	// AcceptSecContext. If no token need be sent, InitSecContext will indicate this by setting
 | ||||||
|  | 	// needContinue to false. To complete the context
 | ||||||
|  | 	// establishment, one or more reply tokens may be required from the ssh
 | ||||||
|  | 	// server;if so, InitSecContext will return a needContinue which is true.
 | ||||||
|  | 	// In this case, InitSecContext should be called again when the
 | ||||||
|  | 	// reply token is received from the ssh server, passing the reply
 | ||||||
|  | 	// token to InitSecContext via the token parameters.
 | ||||||
|  | 	// See RFC 2743 section 2.2.1 and RFC 4462 section 3.4.
 | ||||||
|  | 	InitSecContext(target string, token []byte, isGSSDelegCreds bool) (outputToken []byte, needContinue bool, err error) | ||||||
|  | 	// GetMIC generates a cryptographic MIC for the SSH2 message, and places
 | ||||||
|  | 	// the MIC in a token for transfer to the ssh server.
 | ||||||
|  | 	// The contents of the MIC field are obtained by calling GSS_GetMIC()
 | ||||||
|  | 	// over the following, using the GSS-API context that was just
 | ||||||
|  | 	// established:
 | ||||||
|  | 	//  string    session identifier
 | ||||||
|  | 	//  byte      SSH_MSG_USERAUTH_REQUEST
 | ||||||
|  | 	//  string    user name
 | ||||||
|  | 	//  string    service
 | ||||||
|  | 	//  string    "gssapi-with-mic"
 | ||||||
|  | 	// See RFC 2743 section 2.3.1 and RFC 4462 3.5.
 | ||||||
|  | 	GetMIC(micFiled []byte) ([]byte, error) | ||||||
|  | 	// Whenever possible, it should be possible for
 | ||||||
|  | 	// DeleteSecContext() calls to be successfully processed even
 | ||||||
|  | 	// if other calls cannot succeed, thereby enabling context-related
 | ||||||
|  | 	// resources to be released.
 | ||||||
|  | 	// In addition to deleting established security contexts,
 | ||||||
|  | 	// gss_delete_sec_context must also be able to delete "half-built"
 | ||||||
|  | 	// security contexts resulting from an incomplete sequence of
 | ||||||
|  | 	// InitSecContext()/AcceptSecContext() calls.
 | ||||||
|  | 	// See RFC 2743 section 2.2.3.
 | ||||||
|  | 	DeleteSecContext() error | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GSSAPIServer provides the API to plug in GSSAPI authentication for server logins.
 | ||||||
|  | type GSSAPIServer interface { | ||||||
|  | 	// AcceptSecContext allows a remotely initiated security context between the application
 | ||||||
|  | 	// and a remote peer to be established by the ssh client. The routine may return a
 | ||||||
|  | 	// outputToken which should be transferred to the ssh client,
 | ||||||
|  | 	// where the ssh client will present it to InitSecContext.
 | ||||||
|  | 	// If no token need be sent, AcceptSecContext will indicate this
 | ||||||
|  | 	// by setting the needContinue to false. To
 | ||||||
|  | 	// complete the context establishment, one or more reply tokens may be
 | ||||||
|  | 	// required from the ssh client. if so, AcceptSecContext
 | ||||||
|  | 	// will return a needContinue which is true, in which case it
 | ||||||
|  | 	// should be called again when the reply token is received from the ssh
 | ||||||
|  | 	// client, passing the token to AcceptSecContext via the
 | ||||||
|  | 	// token parameters.
 | ||||||
|  | 	// The srcName return value is the authenticated username.
 | ||||||
|  | 	// See RFC 2743 section 2.2.2 and RFC 4462 section 3.4.
 | ||||||
|  | 	AcceptSecContext(token []byte) (outputToken []byte, srcName string, needContinue bool, err error) | ||||||
|  | 	// VerifyMIC verifies that a cryptographic MIC, contained in the token parameter,
 | ||||||
|  | 	// fits the supplied message is received from the ssh client.
 | ||||||
|  | 	// See RFC 2743 section 2.3.2.
 | ||||||
|  | 	VerifyMIC(micField []byte, micToken []byte) error | ||||||
|  | 	// Whenever possible, it should be possible for
 | ||||||
|  | 	// DeleteSecContext() calls to be successfully processed even
 | ||||||
|  | 	// if other calls cannot succeed, thereby enabling context-related
 | ||||||
|  | 	// resources to be released.
 | ||||||
|  | 	// In addition to deleting established security contexts,
 | ||||||
|  | 	// gss_delete_sec_context must also be able to delete "half-built"
 | ||||||
|  | 	// security contexts resulting from an incomplete sequence of
 | ||||||
|  | 	// InitSecContext()/AcceptSecContext() calls.
 | ||||||
|  | 	// See RFC 2743 section 2.2.3.
 | ||||||
|  | 	DeleteSecContext() error | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,
 | ||||||
|  | 	// so we also support the krb5 mechanism only.
 | ||||||
|  | 	// See RFC 1964 section 1.
 | ||||||
|  | 	krb5Mesh = asn1.ObjectIdentifier{1, 2, 840, 113554, 1, 2, 2} | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST
 | ||||||
|  | // See RFC 4462 section 3.2.
 | ||||||
|  | type userAuthRequestGSSAPI struct { | ||||||
|  | 	N    uint32 | ||||||
|  | 	OIDS []asn1.ObjectIdentifier | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parseGSSAPIPayload(payload []byte) (*userAuthRequestGSSAPI, error) { | ||||||
|  | 	n, rest, ok := parseUint32(payload) | ||||||
|  | 	if !ok { | ||||||
|  | 		return nil, errors.New("parse uint32 failed") | ||||||
|  | 	} | ||||||
|  | 	s := &userAuthRequestGSSAPI{ | ||||||
|  | 		N:    n, | ||||||
|  | 		OIDS: make([]asn1.ObjectIdentifier, n), | ||||||
|  | 	} | ||||||
|  | 	for i := 0; i < int(n); i++ { | ||||||
|  | 		var ( | ||||||
|  | 			desiredMech []byte | ||||||
|  | 			err         error | ||||||
|  | 		) | ||||||
|  | 		desiredMech, rest, ok = parseString(rest) | ||||||
|  | 		if !ok { | ||||||
|  | 			return nil, errors.New("parse string failed") | ||||||
|  | 		} | ||||||
|  | 		if rest, err = asn1.Unmarshal(desiredMech, &s.OIDS[i]); err != nil { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	} | ||||||
|  | 	return s, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // See RFC 4462 section 3.6.
 | ||||||
|  | func buildMIC(sessionID string, username string, service string, authMethod string) []byte { | ||||||
|  | 	out := make([]byte, 0, 0) | ||||||
|  | 	out = appendString(out, sessionID) | ||||||
|  | 	out = append(out, msgUserAuthRequest) | ||||||
|  | 	out = appendString(out, username) | ||||||
|  | 	out = appendString(out, service) | ||||||
|  | 	out = appendString(out, authMethod) | ||||||
|  | 	return out | ||||||
|  | } | ||||||
|  | @ -7,6 +7,7 @@ package terminal | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"strconv" | ||||||
| 	"sync" | 	"sync" | ||||||
| 	"unicode/utf8" | 	"unicode/utf8" | ||||||
| ) | ) | ||||||
|  | @ -271,34 +272,44 @@ func (t *Terminal) moveCursorToPos(pos int) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (t *Terminal) move(up, down, left, right int) { | func (t *Terminal) move(up, down, left, right int) { | ||||||
| 	movement := make([]rune, 3*(up+down+left+right)) | 	m := []rune{} | ||||||
| 	m := movement | 
 | ||||||
| 	for i := 0; i < up; i++ { | 	// 1 unit up can be expressed as ^[[A or ^[A
 | ||||||
| 		m[0] = keyEscape | 	// 5 units up can be expressed as ^[[5A
 | ||||||
| 		m[1] = '[' | 
 | ||||||
| 		m[2] = 'A' | 	if up == 1 { | ||||||
| 		m = m[3:] | 		m = append(m, keyEscape, '[', 'A') | ||||||
| 	} | 	} else if up > 1 { | ||||||
| 	for i := 0; i < down; i++ { | 		m = append(m, keyEscape, '[') | ||||||
| 		m[0] = keyEscape | 		m = append(m, []rune(strconv.Itoa(up))...) | ||||||
| 		m[1] = '[' | 		m = append(m, 'A') | ||||||
| 		m[2] = 'B' |  | ||||||
| 		m = m[3:] |  | ||||||
| 	} |  | ||||||
| 	for i := 0; i < left; i++ { |  | ||||||
| 		m[0] = keyEscape |  | ||||||
| 		m[1] = '[' |  | ||||||
| 		m[2] = 'D' |  | ||||||
| 		m = m[3:] |  | ||||||
| 	} |  | ||||||
| 	for i := 0; i < right; i++ { |  | ||||||
| 		m[0] = keyEscape |  | ||||||
| 		m[1] = '[' |  | ||||||
| 		m[2] = 'C' |  | ||||||
| 		m = m[3:] |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	t.queue(movement) | 	if down == 1 { | ||||||
|  | 		m = append(m, keyEscape, '[', 'B') | ||||||
|  | 	} else if down > 1 { | ||||||
|  | 		m = append(m, keyEscape, '[') | ||||||
|  | 		m = append(m, []rune(strconv.Itoa(down))...) | ||||||
|  | 		m = append(m, 'B') | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if right == 1 { | ||||||
|  | 		m = append(m, keyEscape, '[', 'C') | ||||||
|  | 	} else if right > 1 { | ||||||
|  | 		m = append(m, keyEscape, '[') | ||||||
|  | 		m = append(m, []rune(strconv.Itoa(right))...) | ||||||
|  | 		m = append(m, 'C') | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if left == 1 { | ||||||
|  | 		m = append(m, keyEscape, '[', 'D') | ||||||
|  | 	} else if left > 1 { | ||||||
|  | 		m = append(m, keyEscape, '[') | ||||||
|  | 		m = append(m, []rune(strconv.Itoa(left))...) | ||||||
|  | 		m = append(m, 'D') | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.queue(m) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (t *Terminal) clearLineToRight() { | func (t *Terminal) clearLineToRight() { | ||||||
|  |  | ||||||
|  | @ -53,14 +53,14 @@ type transport struct { | ||||||
| // packetCipher represents a combination of SSH encryption/MAC
 | // packetCipher represents a combination of SSH encryption/MAC
 | ||||||
| // protocol.  A single instance should be used for one direction only.
 | // protocol.  A single instance should be used for one direction only.
 | ||||||
| type packetCipher interface { | type packetCipher interface { | ||||||
| 	// writePacket encrypts the packet and writes it to w. The
 | 	// writeCipherPacket encrypts the packet and writes it to w. The
 | ||||||
| 	// contents of the packet are generally scrambled.
 | 	// contents of the packet are generally scrambled.
 | ||||||
| 	writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error | 	writeCipherPacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error | ||||||
| 
 | 
 | ||||||
| 	// readPacket reads and decrypts a packet of data. The
 | 	// readCipherPacket reads and decrypts a packet of data. The
 | ||||||
| 	// returned packet may be overwritten by future calls of
 | 	// returned packet may be overwritten by future calls of
 | ||||||
| 	// readPacket.
 | 	// readPacket.
 | ||||||
| 	readPacket(seqnum uint32, r io.Reader) ([]byte, error) | 	readCipherPacket(seqnum uint32, r io.Reader) ([]byte, error) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // connectionState represents one side (read or write) of the
 | // connectionState represents one side (read or write) of the
 | ||||||
|  | @ -127,7 +127,7 @@ func (t *transport) readPacket() (p []byte, err error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { | func (s *connectionState) readPacket(r *bufio.Reader) ([]byte, error) { | ||||||
| 	packet, err := s.packetCipher.readPacket(s.seqNum, r) | 	packet, err := s.packetCipher.readCipherPacket(s.seqNum, r) | ||||||
| 	s.seqNum++ | 	s.seqNum++ | ||||||
| 	if err == nil && len(packet) == 0 { | 	if err == nil && len(packet) == 0 { | ||||||
| 		err = errors.New("ssh: zero length packet") | 		err = errors.New("ssh: zero length packet") | ||||||
|  | @ -175,7 +175,7 @@ func (t *transport) writePacket(packet []byte) error { | ||||||
| func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { | func (s *connectionState) writePacket(w *bufio.Writer, rand io.Reader, packet []byte) error { | ||||||
| 	changeKeys := len(packet) > 0 && packet[0] == msgNewKeys | 	changeKeys := len(packet) > 0 && packet[0] == msgNewKeys | ||||||
| 
 | 
 | ||||||
| 	err := s.packetCipher.writePacket(s.seqNum, w, rand, packet) | 	err := s.packetCipher.writeCipherPacket(s.seqNum, w, rand, packet) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -153,6 +153,11 @@ func main() { | ||||||
| 			} | 			} | ||||||
| 			funct, inps, outps, sysname := f[2], f[3], f[4], f[5] | 			funct, inps, outps, sysname := f[2], f[3], f[4], f[5] | ||||||
| 
 | 
 | ||||||
|  | 			// ClockGettime doesn't have a syscall number on Darwin, only generate libc wrappers.
 | ||||||
|  | 			if goos == "darwin" && !libc && funct == "ClockGettime" { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			// Split argument lists on comma.
 | 			// Split argument lists on comma.
 | ||||||
| 			in := parseParamList(inps) | 			in := parseParamList(inps) | ||||||
| 			out := parseParamList(outps) | 			out := parseParamList(outps) | ||||||
|  |  | ||||||
|  | @ -144,6 +144,23 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) ( | ||||||
| 
 | 
 | ||||||
| //sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error)
 | //sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error)
 | ||||||
| 
 | 
 | ||||||
|  | func SysctlClockinfo(name string) (*Clockinfo, error) { | ||||||
|  | 	mib, err := sysctlmib(name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	n := uintptr(SizeofClockinfo) | ||||||
|  | 	var ci Clockinfo | ||||||
|  | 	if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if n != SizeofClockinfo { | ||||||
|  | 		return nil, EIO | ||||||
|  | 	} | ||||||
|  | 	return &ci, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| //sysnb pipe() (r int, w int, err error)
 | //sysnb pipe() (r int, w int, err error)
 | ||||||
| 
 | 
 | ||||||
| func Pipe(p []int) (err error) { | func Pipe(p []int) (err error) { | ||||||
|  |  | ||||||
|  | @ -43,6 +43,23 @@ func nametomib(name string) (mib []_C_int, err error) { | ||||||
| 	return nil, EINVAL | 	return nil, EINVAL | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func SysctlClockinfo(name string) (*Clockinfo, error) { | ||||||
|  | 	mib, err := sysctlmib(name) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	n := uintptr(SizeofClockinfo) | ||||||
|  | 	var ci Clockinfo | ||||||
|  | 	if err := sysctl(mib, (*byte)(unsafe.Pointer(&ci)), &n, nil, 0); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	if n != SizeofClockinfo { | ||||||
|  | 		return nil, EIO | ||||||
|  | 	} | ||||||
|  | 	return &ci, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func SysctlUvmexp(name string) (*Uvmexp, error) { | func SysctlUvmexp(name string) (*Uvmexp, error) { | ||||||
| 	mib, err := sysctlmib(name) | 	mib, err := sysctlmib(name) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
|  | @ -294,6 +294,13 @@ func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) { | ||||||
| 	return &tv, err | 	return &tv, err | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func GetsockoptUint64(fd, level, opt int) (value uint64, err error) { | ||||||
|  | 	var n uint64 | ||||||
|  | 	vallen := _Socklen(8) | ||||||
|  | 	err = getsockopt(fd, level, opt, unsafe.Pointer(&n), &vallen) | ||||||
|  | 	return n, err | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { | func Recvfrom(fd int, p []byte, flags int) (n int, from Sockaddr, err error) { | ||||||
| 	var rsa RawSockaddrAny | 	var rsa RawSockaddrAny | ||||||
| 	var len _Socklen = SizeofSockaddrAny | 	var len _Socklen = SizeofSockaddrAny | ||||||
|  | @ -344,13 +351,21 @@ func SetsockoptLinger(fd, level, opt int, l *Linger) (err error) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func SetsockoptString(fd, level, opt int, s string) (err error) { | func SetsockoptString(fd, level, opt int, s string) (err error) { | ||||||
| 	return setsockopt(fd, level, opt, unsafe.Pointer(&[]byte(s)[0]), uintptr(len(s))) | 	var p unsafe.Pointer | ||||||
|  | 	if len(s) > 0 { | ||||||
|  | 		p = unsafe.Pointer(&[]byte(s)[0]) | ||||||
|  | 	} | ||||||
|  | 	return setsockopt(fd, level, opt, p, uintptr(len(s))) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { | func SetsockoptTimeval(fd, level, opt int, tv *Timeval) (err error) { | ||||||
| 	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv)) | 	return setsockopt(fd, level, opt, unsafe.Pointer(tv), unsafe.Sizeof(*tv)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func SetsockoptUint64(fd, level, opt int, value uint64) (err error) { | ||||||
|  | 	return setsockopt(fd, level, opt, unsafe.Pointer(&value), 8) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func Socket(domain, typ, proto int) (fd int, err error) { | func Socket(domain, typ, proto int) (fd int, err error) { | ||||||
| 	if domain == AF_INET6 && SocketDisableIPv6 { | 	if domain == AF_INET6 && SocketDisableIPv6 { | ||||||
| 		return -1, EAFNOSUPPORT | 		return -1, EAFNOSUPPORT | ||||||
|  |  | ||||||
|  | @ -275,3 +275,9 @@ const ( | ||||||
| // uname
 | // uname
 | ||||||
| 
 | 
 | ||||||
| type Utsname C.struct_utsname | type Utsname C.struct_utsname | ||||||
|  | 
 | ||||||
|  | // Clockinfo
 | ||||||
|  | 
 | ||||||
|  | const SizeofClockinfo = C.sizeof_struct_clockinfo | ||||||
|  | 
 | ||||||
|  | type Clockinfo C.struct_clockinfo | ||||||
|  |  | ||||||
|  | @ -274,3 +274,9 @@ type Utsname C.struct_utsname | ||||||
| const SizeofUvmexp = C.sizeof_struct_uvmexp | const SizeofUvmexp = C.sizeof_struct_uvmexp | ||||||
| 
 | 
 | ||||||
| type Uvmexp C.struct_uvmexp | type Uvmexp C.struct_uvmexp | ||||||
|  | 
 | ||||||
|  | // Clockinfo
 | ||||||
|  | 
 | ||||||
|  | const SizeofClockinfo = C.sizeof_struct_clockinfo | ||||||
|  | 
 | ||||||
|  | type Clockinfo C.struct_clockinfo | ||||||
|  |  | ||||||
|  | @ -487,3 +487,13 @@ type Utsname struct { | ||||||
| 	Version  [256]byte | 	Version  [256]byte | ||||||
| 	Machine  [256]byte | 	Machine  [256]byte | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | const SizeofClockinfo = 0x14 | ||||||
|  | 
 | ||||||
|  | type Clockinfo struct { | ||||||
|  | 	Hz      int32 | ||||||
|  | 	Tick    int32 | ||||||
|  | 	Tickadj int32 | ||||||
|  | 	Stathz  int32 | ||||||
|  | 	Profhz  int32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -497,3 +497,13 @@ type Utsname struct { | ||||||
| 	Version  [256]byte | 	Version  [256]byte | ||||||
| 	Machine  [256]byte | 	Machine  [256]byte | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | const SizeofClockinfo = 0x14 | ||||||
|  | 
 | ||||||
|  | type Clockinfo struct { | ||||||
|  | 	Hz      int32 | ||||||
|  | 	Tick    int32 | ||||||
|  | 	Tickadj int32 | ||||||
|  | 	Stathz  int32 | ||||||
|  | 	Profhz  int32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -488,3 +488,13 @@ type Utsname struct { | ||||||
| 	Version  [256]byte | 	Version  [256]byte | ||||||
| 	Machine  [256]byte | 	Machine  [256]byte | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | const SizeofClockinfo = 0x14 | ||||||
|  | 
 | ||||||
|  | type Clockinfo struct { | ||||||
|  | 	Hz      int32 | ||||||
|  | 	Tick    int32 | ||||||
|  | 	Tickadj int32 | ||||||
|  | 	Stathz  int32 | ||||||
|  | 	Profhz  int32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -497,3 +497,13 @@ type Utsname struct { | ||||||
| 	Version  [256]byte | 	Version  [256]byte | ||||||
| 	Machine  [256]byte | 	Machine  [256]byte | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | const SizeofClockinfo = 0x14 | ||||||
|  | 
 | ||||||
|  | type Clockinfo struct { | ||||||
|  | 	Hz      int32 | ||||||
|  | 	Tick    int32 | ||||||
|  | 	Tickadj int32 | ||||||
|  | 	Stathz  int32 | ||||||
|  | 	Profhz  int32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -443,139 +443,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -652,6 +694,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x8 | 	SizeofSockFprog  = 0x8 | ||||||
|  |  | ||||||
|  | @ -444,139 +444,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -653,6 +695,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x10 | 	SizeofSockFprog  = 0x10 | ||||||
|  |  | ||||||
|  | @ -447,139 +447,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -656,6 +698,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x8 | 	SizeofSockFprog  = 0x8 | ||||||
|  |  | ||||||
|  | @ -445,139 +445,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -654,6 +696,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x10 | 	SizeofSockFprog  = 0x10 | ||||||
|  |  | ||||||
|  | @ -446,139 +446,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -655,6 +697,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x8 | 	SizeofSockFprog  = 0x8 | ||||||
|  |  | ||||||
|  | @ -445,139 +445,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -654,6 +696,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x10 | 	SizeofSockFprog  = 0x10 | ||||||
|  |  | ||||||
|  | @ -445,139 +445,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -654,6 +696,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x10 | 	SizeofSockFprog  = 0x10 | ||||||
|  |  | ||||||
|  | @ -446,139 +446,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -655,6 +697,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x8 | 	SizeofSockFprog  = 0x8 | ||||||
|  |  | ||||||
|  | @ -446,139 +446,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -655,6 +697,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x10 | 	SizeofSockFprog  = 0x10 | ||||||
|  |  | ||||||
|  | @ -446,139 +446,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -655,6 +697,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x10 | 	SizeofSockFprog  = 0x10 | ||||||
|  |  | ||||||
|  | @ -445,139 +445,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -654,6 +696,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x10 | 	SizeofSockFprog  = 0x10 | ||||||
|  |  | ||||||
|  | @ -444,139 +444,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -653,6 +695,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x10 | 	SizeofSockFprog  = 0x10 | ||||||
|  |  | ||||||
|  | @ -448,139 +448,181 @@ const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	IFA_UNSPEC           = 0x0 | 	NDA_UNSPEC              = 0x0 | ||||||
| 	IFA_ADDRESS          = 0x1 | 	NDA_DST                 = 0x1 | ||||||
| 	IFA_LOCAL            = 0x2 | 	NDA_LLADDR              = 0x2 | ||||||
| 	IFA_LABEL            = 0x3 | 	NDA_CACHEINFO           = 0x3 | ||||||
| 	IFA_BROADCAST        = 0x4 | 	NDA_PROBES              = 0x4 | ||||||
| 	IFA_ANYCAST          = 0x5 | 	NDA_VLAN                = 0x5 | ||||||
| 	IFA_CACHEINFO        = 0x6 | 	NDA_PORT                = 0x6 | ||||||
| 	IFA_MULTICAST        = 0x7 | 	NDA_VNI                 = 0x7 | ||||||
| 	IFLA_UNSPEC          = 0x0 | 	NDA_IFINDEX             = 0x8 | ||||||
| 	IFLA_ADDRESS         = 0x1 | 	NDA_MASTER              = 0x9 | ||||||
| 	IFLA_BROADCAST       = 0x2 | 	NDA_LINK_NETNSID        = 0xa | ||||||
| 	IFLA_IFNAME          = 0x3 | 	NDA_SRC_VNI             = 0xb | ||||||
| 	IFLA_INFO_KIND       = 0x1 | 	NTF_USE                 = 0x1 | ||||||
| 	IFLA_MTU             = 0x4 | 	NTF_SELF                = 0x2 | ||||||
| 	IFLA_LINK            = 0x5 | 	NTF_MASTER              = 0x4 | ||||||
| 	IFLA_QDISC           = 0x6 | 	NTF_PROXY               = 0x8 | ||||||
| 	IFLA_STATS           = 0x7 | 	NTF_EXT_LEARNED         = 0x10 | ||||||
| 	IFLA_COST            = 0x8 | 	NTF_OFFLOADED           = 0x20 | ||||||
| 	IFLA_PRIORITY        = 0x9 | 	NTF_ROUTER              = 0x80 | ||||||
| 	IFLA_MASTER          = 0xa | 	NUD_INCOMPLETE          = 0x1 | ||||||
| 	IFLA_WIRELESS        = 0xb | 	NUD_REACHABLE           = 0x2 | ||||||
| 	IFLA_PROTINFO        = 0xc | 	NUD_STALE               = 0x4 | ||||||
| 	IFLA_TXQLEN          = 0xd | 	NUD_DELAY               = 0x8 | ||||||
| 	IFLA_MAP             = 0xe | 	NUD_PROBE               = 0x10 | ||||||
| 	IFLA_WEIGHT          = 0xf | 	NUD_FAILED              = 0x20 | ||||||
| 	IFLA_OPERSTATE       = 0x10 | 	NUD_NOARP               = 0x40 | ||||||
| 	IFLA_LINKMODE        = 0x11 | 	NUD_PERMANENT           = 0x80 | ||||||
| 	IFLA_LINKINFO        = 0x12 | 	NUD_NONE                = 0x0 | ||||||
| 	IFLA_NET_NS_PID      = 0x13 | 	IFA_UNSPEC              = 0x0 | ||||||
| 	IFLA_IFALIAS         = 0x14 | 	IFA_ADDRESS             = 0x1 | ||||||
| 	IFLA_NUM_VF          = 0x15 | 	IFA_LOCAL               = 0x2 | ||||||
| 	IFLA_VFINFO_LIST     = 0x16 | 	IFA_LABEL               = 0x3 | ||||||
| 	IFLA_STATS64         = 0x17 | 	IFA_BROADCAST           = 0x4 | ||||||
| 	IFLA_VF_PORTS        = 0x18 | 	IFA_ANYCAST             = 0x5 | ||||||
| 	IFLA_PORT_SELF       = 0x19 | 	IFA_CACHEINFO           = 0x6 | ||||||
| 	IFLA_AF_SPEC         = 0x1a | 	IFA_MULTICAST           = 0x7 | ||||||
| 	IFLA_GROUP           = 0x1b | 	IFA_FLAGS               = 0x8 | ||||||
| 	IFLA_NET_NS_FD       = 0x1c | 	IFA_RT_PRIORITY         = 0x9 | ||||||
| 	IFLA_EXT_MASK        = 0x1d | 	IFA_TARGET_NETNSID      = 0xa | ||||||
| 	IFLA_PROMISCUITY     = 0x1e | 	IFLA_UNSPEC             = 0x0 | ||||||
| 	IFLA_NUM_TX_QUEUES   = 0x1f | 	IFLA_ADDRESS            = 0x1 | ||||||
| 	IFLA_NUM_RX_QUEUES   = 0x20 | 	IFLA_BROADCAST          = 0x2 | ||||||
| 	IFLA_CARRIER         = 0x21 | 	IFLA_IFNAME             = 0x3 | ||||||
| 	IFLA_PHYS_PORT_ID    = 0x22 | 	IFLA_MTU                = 0x4 | ||||||
| 	IFLA_CARRIER_CHANGES = 0x23 | 	IFLA_LINK               = 0x5 | ||||||
| 	IFLA_PHYS_SWITCH_ID  = 0x24 | 	IFLA_QDISC              = 0x6 | ||||||
| 	IFLA_LINK_NETNSID    = 0x25 | 	IFLA_STATS              = 0x7 | ||||||
| 	IFLA_PHYS_PORT_NAME  = 0x26 | 	IFLA_COST               = 0x8 | ||||||
| 	IFLA_PROTO_DOWN      = 0x27 | 	IFLA_PRIORITY           = 0x9 | ||||||
| 	IFLA_GSO_MAX_SEGS    = 0x28 | 	IFLA_MASTER             = 0xa | ||||||
| 	IFLA_GSO_MAX_SIZE    = 0x29 | 	IFLA_WIRELESS           = 0xb | ||||||
| 	IFLA_PAD             = 0x2a | 	IFLA_PROTINFO           = 0xc | ||||||
| 	IFLA_XDP             = 0x2b | 	IFLA_TXQLEN             = 0xd | ||||||
| 	IFLA_EVENT           = 0x2c | 	IFLA_MAP                = 0xe | ||||||
| 	IFLA_NEW_NETNSID     = 0x2d | 	IFLA_WEIGHT             = 0xf | ||||||
| 	IFLA_IF_NETNSID      = 0x2e | 	IFLA_OPERSTATE          = 0x10 | ||||||
| 	IFLA_MAX             = 0x33 | 	IFLA_LINKMODE           = 0x11 | ||||||
| 	RT_SCOPE_UNIVERSE    = 0x0 | 	IFLA_LINKINFO           = 0x12 | ||||||
| 	RT_SCOPE_SITE        = 0xc8 | 	IFLA_NET_NS_PID         = 0x13 | ||||||
| 	RT_SCOPE_LINK        = 0xfd | 	IFLA_IFALIAS            = 0x14 | ||||||
| 	RT_SCOPE_HOST        = 0xfe | 	IFLA_NUM_VF             = 0x15 | ||||||
| 	RT_SCOPE_NOWHERE     = 0xff | 	IFLA_VFINFO_LIST        = 0x16 | ||||||
| 	RT_TABLE_UNSPEC      = 0x0 | 	IFLA_STATS64            = 0x17 | ||||||
| 	RT_TABLE_COMPAT      = 0xfc | 	IFLA_VF_PORTS           = 0x18 | ||||||
| 	RT_TABLE_DEFAULT     = 0xfd | 	IFLA_PORT_SELF          = 0x19 | ||||||
| 	RT_TABLE_MAIN        = 0xfe | 	IFLA_AF_SPEC            = 0x1a | ||||||
| 	RT_TABLE_LOCAL       = 0xff | 	IFLA_GROUP              = 0x1b | ||||||
| 	RT_TABLE_MAX         = 0xffffffff | 	IFLA_NET_NS_FD          = 0x1c | ||||||
| 	RTA_UNSPEC           = 0x0 | 	IFLA_EXT_MASK           = 0x1d | ||||||
| 	RTA_DST              = 0x1 | 	IFLA_PROMISCUITY        = 0x1e | ||||||
| 	RTA_SRC              = 0x2 | 	IFLA_NUM_TX_QUEUES      = 0x1f | ||||||
| 	RTA_IIF              = 0x3 | 	IFLA_NUM_RX_QUEUES      = 0x20 | ||||||
| 	RTA_OIF              = 0x4 | 	IFLA_CARRIER            = 0x21 | ||||||
| 	RTA_GATEWAY          = 0x5 | 	IFLA_PHYS_PORT_ID       = 0x22 | ||||||
| 	RTA_PRIORITY         = 0x6 | 	IFLA_CARRIER_CHANGES    = 0x23 | ||||||
| 	RTA_PREFSRC          = 0x7 | 	IFLA_PHYS_SWITCH_ID     = 0x24 | ||||||
| 	RTA_METRICS          = 0x8 | 	IFLA_LINK_NETNSID       = 0x25 | ||||||
| 	RTA_MULTIPATH        = 0x9 | 	IFLA_PHYS_PORT_NAME     = 0x26 | ||||||
| 	RTA_FLOW             = 0xb | 	IFLA_PROTO_DOWN         = 0x27 | ||||||
| 	RTA_CACHEINFO        = 0xc | 	IFLA_GSO_MAX_SEGS       = 0x28 | ||||||
| 	RTA_TABLE            = 0xf | 	IFLA_GSO_MAX_SIZE       = 0x29 | ||||||
| 	RTA_MARK             = 0x10 | 	IFLA_PAD                = 0x2a | ||||||
| 	RTA_MFC_STATS        = 0x11 | 	IFLA_XDP                = 0x2b | ||||||
| 	RTA_VIA              = 0x12 | 	IFLA_EVENT              = 0x2c | ||||||
| 	RTA_NEWDST           = 0x13 | 	IFLA_NEW_NETNSID        = 0x2d | ||||||
| 	RTA_PREF             = 0x14 | 	IFLA_IF_NETNSID         = 0x2e | ||||||
| 	RTA_ENCAP_TYPE       = 0x15 | 	IFLA_TARGET_NETNSID     = 0x2e | ||||||
| 	RTA_ENCAP            = 0x16 | 	IFLA_CARRIER_UP_COUNT   = 0x2f | ||||||
| 	RTA_EXPIRES          = 0x17 | 	IFLA_CARRIER_DOWN_COUNT = 0x30 | ||||||
| 	RTA_PAD              = 0x18 | 	IFLA_NEW_IFINDEX        = 0x31 | ||||||
| 	RTA_UID              = 0x19 | 	IFLA_MIN_MTU            = 0x32 | ||||||
| 	RTA_TTL_PROPAGATE    = 0x1a | 	IFLA_MAX_MTU            = 0x33 | ||||||
| 	RTA_IP_PROTO         = 0x1b | 	IFLA_MAX                = 0x33 | ||||||
| 	RTA_SPORT            = 0x1c | 	IFLA_INFO_KIND          = 0x1 | ||||||
| 	RTA_DPORT            = 0x1d | 	IFLA_INFO_DATA          = 0x2 | ||||||
| 	RTN_UNSPEC           = 0x0 | 	IFLA_INFO_XSTATS        = 0x3 | ||||||
| 	RTN_UNICAST          = 0x1 | 	IFLA_INFO_SLAVE_KIND    = 0x4 | ||||||
| 	RTN_LOCAL            = 0x2 | 	IFLA_INFO_SLAVE_DATA    = 0x5 | ||||||
| 	RTN_BROADCAST        = 0x3 | 	RT_SCOPE_UNIVERSE       = 0x0 | ||||||
| 	RTN_ANYCAST          = 0x4 | 	RT_SCOPE_SITE           = 0xc8 | ||||||
| 	RTN_MULTICAST        = 0x5 | 	RT_SCOPE_LINK           = 0xfd | ||||||
| 	RTN_BLACKHOLE        = 0x6 | 	RT_SCOPE_HOST           = 0xfe | ||||||
| 	RTN_UNREACHABLE      = 0x7 | 	RT_SCOPE_NOWHERE        = 0xff | ||||||
| 	RTN_PROHIBIT         = 0x8 | 	RT_TABLE_UNSPEC         = 0x0 | ||||||
| 	RTN_THROW            = 0x9 | 	RT_TABLE_COMPAT         = 0xfc | ||||||
| 	RTN_NAT              = 0xa | 	RT_TABLE_DEFAULT        = 0xfd | ||||||
| 	RTN_XRESOLVE         = 0xb | 	RT_TABLE_MAIN           = 0xfe | ||||||
| 	RTNLGRP_NONE         = 0x0 | 	RT_TABLE_LOCAL          = 0xff | ||||||
| 	RTNLGRP_LINK         = 0x1 | 	RT_TABLE_MAX            = 0xffffffff | ||||||
| 	RTNLGRP_NOTIFY       = 0x2 | 	RTA_UNSPEC              = 0x0 | ||||||
| 	RTNLGRP_NEIGH        = 0x3 | 	RTA_DST                 = 0x1 | ||||||
| 	RTNLGRP_TC           = 0x4 | 	RTA_SRC                 = 0x2 | ||||||
| 	RTNLGRP_IPV4_IFADDR  = 0x5 | 	RTA_IIF                 = 0x3 | ||||||
| 	RTNLGRP_IPV4_MROUTE  = 0x6 | 	RTA_OIF                 = 0x4 | ||||||
| 	RTNLGRP_IPV4_ROUTE   = 0x7 | 	RTA_GATEWAY             = 0x5 | ||||||
| 	RTNLGRP_IPV4_RULE    = 0x8 | 	RTA_PRIORITY            = 0x6 | ||||||
| 	RTNLGRP_IPV6_IFADDR  = 0x9 | 	RTA_PREFSRC             = 0x7 | ||||||
| 	RTNLGRP_IPV6_MROUTE  = 0xa | 	RTA_METRICS             = 0x8 | ||||||
| 	RTNLGRP_IPV6_ROUTE   = 0xb | 	RTA_MULTIPATH           = 0x9 | ||||||
| 	RTNLGRP_IPV6_IFINFO  = 0xc | 	RTA_FLOW                = 0xb | ||||||
| 	RTNLGRP_IPV6_PREFIX  = 0x12 | 	RTA_CACHEINFO           = 0xc | ||||||
| 	RTNLGRP_IPV6_RULE    = 0x13 | 	RTA_TABLE               = 0xf | ||||||
| 	RTNLGRP_ND_USEROPT   = 0x14 | 	RTA_MARK                = 0x10 | ||||||
| 	SizeofNlMsghdr       = 0x10 | 	RTA_MFC_STATS           = 0x11 | ||||||
| 	SizeofNlMsgerr       = 0x14 | 	RTA_VIA                 = 0x12 | ||||||
| 	SizeofRtGenmsg       = 0x1 | 	RTA_NEWDST              = 0x13 | ||||||
| 	SizeofNlAttr         = 0x4 | 	RTA_PREF                = 0x14 | ||||||
| 	SizeofRtAttr         = 0x4 | 	RTA_ENCAP_TYPE          = 0x15 | ||||||
| 	SizeofIfInfomsg      = 0x10 | 	RTA_ENCAP               = 0x16 | ||||||
| 	SizeofIfAddrmsg      = 0x8 | 	RTA_EXPIRES             = 0x17 | ||||||
| 	SizeofRtMsg          = 0xc | 	RTA_PAD                 = 0x18 | ||||||
| 	SizeofRtNexthop      = 0x8 | 	RTA_UID                 = 0x19 | ||||||
| 	SizeofNdUseroptmsg   = 0x10 | 	RTA_TTL_PROPAGATE       = 0x1a | ||||||
|  | 	RTA_IP_PROTO            = 0x1b | ||||||
|  | 	RTA_SPORT               = 0x1c | ||||||
|  | 	RTA_DPORT               = 0x1d | ||||||
|  | 	RTN_UNSPEC              = 0x0 | ||||||
|  | 	RTN_UNICAST             = 0x1 | ||||||
|  | 	RTN_LOCAL               = 0x2 | ||||||
|  | 	RTN_BROADCAST           = 0x3 | ||||||
|  | 	RTN_ANYCAST             = 0x4 | ||||||
|  | 	RTN_MULTICAST           = 0x5 | ||||||
|  | 	RTN_BLACKHOLE           = 0x6 | ||||||
|  | 	RTN_UNREACHABLE         = 0x7 | ||||||
|  | 	RTN_PROHIBIT            = 0x8 | ||||||
|  | 	RTN_THROW               = 0x9 | ||||||
|  | 	RTN_NAT                 = 0xa | ||||||
|  | 	RTN_XRESOLVE            = 0xb | ||||||
|  | 	RTNLGRP_NONE            = 0x0 | ||||||
|  | 	RTNLGRP_LINK            = 0x1 | ||||||
|  | 	RTNLGRP_NOTIFY          = 0x2 | ||||||
|  | 	RTNLGRP_NEIGH           = 0x3 | ||||||
|  | 	RTNLGRP_TC              = 0x4 | ||||||
|  | 	RTNLGRP_IPV4_IFADDR     = 0x5 | ||||||
|  | 	RTNLGRP_IPV4_MROUTE     = 0x6 | ||||||
|  | 	RTNLGRP_IPV4_ROUTE      = 0x7 | ||||||
|  | 	RTNLGRP_IPV4_RULE       = 0x8 | ||||||
|  | 	RTNLGRP_IPV6_IFADDR     = 0x9 | ||||||
|  | 	RTNLGRP_IPV6_MROUTE     = 0xa | ||||||
|  | 	RTNLGRP_IPV6_ROUTE      = 0xb | ||||||
|  | 	RTNLGRP_IPV6_IFINFO     = 0xc | ||||||
|  | 	RTNLGRP_IPV6_PREFIX     = 0x12 | ||||||
|  | 	RTNLGRP_IPV6_RULE       = 0x13 | ||||||
|  | 	RTNLGRP_ND_USEROPT      = 0x14 | ||||||
|  | 	SizeofNlMsghdr          = 0x10 | ||||||
|  | 	SizeofNlMsgerr          = 0x14 | ||||||
|  | 	SizeofRtGenmsg          = 0x1 | ||||||
|  | 	SizeofNlAttr            = 0x4 | ||||||
|  | 	SizeofRtAttr            = 0x4 | ||||||
|  | 	SizeofIfInfomsg         = 0x10 | ||||||
|  | 	SizeofIfAddrmsg         = 0x8 | ||||||
|  | 	SizeofRtMsg             = 0xc | ||||||
|  | 	SizeofRtNexthop         = 0x8 | ||||||
|  | 	SizeofNdUseroptmsg      = 0x10 | ||||||
|  | 	SizeofNdMsg             = 0xc | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type NlMsghdr struct { | type NlMsghdr struct { | ||||||
|  | @ -657,6 +699,16 @@ type NdUseroptmsg struct { | ||||||
| 	Pad3      uint32 | 	Pad3      uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | type NdMsg struct { | ||||||
|  | 	Family  uint8 | ||||||
|  | 	Pad1    uint8 | ||||||
|  | 	Pad2    uint16 | ||||||
|  | 	Ifindex int32 | ||||||
|  | 	State   uint16 | ||||||
|  | 	Flags   uint8 | ||||||
|  | 	Type    uint8 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	SizeofSockFilter = 0x8 | 	SizeofSockFilter = 0x8 | ||||||
| 	SizeofSockFprog  = 0x10 | 	SizeofSockFprog  = 0x10 | ||||||
|  |  | ||||||
|  | @ -558,3 +558,13 @@ type Uvmexp struct { | ||||||
| 	Fpswtch            int32 | 	Fpswtch            int32 | ||||||
| 	Kmapent            int32 | 	Kmapent            int32 | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | const SizeofClockinfo = 0x14 | ||||||
|  | 
 | ||||||
|  | type Clockinfo struct { | ||||||
|  | 	Hz      int32 | ||||||
|  | 	Tick    int32 | ||||||
|  | 	Tickadj int32 | ||||||
|  | 	Stathz  int32 | ||||||
|  | 	Profhz  int32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -558,3 +558,13 @@ type Uvmexp struct { | ||||||
| 	Fpswtch            int32 | 	Fpswtch            int32 | ||||||
| 	Kmapent            int32 | 	Kmapent            int32 | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | const SizeofClockinfo = 0x14 | ||||||
|  | 
 | ||||||
|  | type Clockinfo struct { | ||||||
|  | 	Hz      int32 | ||||||
|  | 	Tick    int32 | ||||||
|  | 	Tickadj int32 | ||||||
|  | 	Stathz  int32 | ||||||
|  | 	Profhz  int32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -559,3 +559,13 @@ type Uvmexp struct { | ||||||
| 	Fpswtch            int32 | 	Fpswtch            int32 | ||||||
| 	Kmapent            int32 | 	Kmapent            int32 | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | const SizeofClockinfo = 0x14 | ||||||
|  | 
 | ||||||
|  | type Clockinfo struct { | ||||||
|  | 	Hz      int32 | ||||||
|  | 	Tick    int32 | ||||||
|  | 	Tickadj int32 | ||||||
|  | 	Stathz  int32 | ||||||
|  | 	Profhz  int32 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ go_library( | ||||||
|         "eventlog.go", |         "eventlog.go", | ||||||
|         "exec_windows.go", |         "exec_windows.go", | ||||||
|         "memory_windows.go", |         "memory_windows.go", | ||||||
|  |         "mkerrors.go", | ||||||
|         "mksyscall.go", |         "mksyscall.go", | ||||||
|         "race.go", |         "race.go", | ||||||
|         "race0.go", |         "race0.go", | ||||||
|  | @ -22,6 +23,7 @@ go_library( | ||||||
|         "types_windows.go", |         "types_windows.go", | ||||||
|         "types_windows_386.go", |         "types_windows_386.go", | ||||||
|         "types_windows_amd64.go", |         "types_windows_amd64.go", | ||||||
|  |         "zerrors_windows.go", | ||||||
|         "zsyscall_windows.go", |         "zsyscall_windows.go", | ||||||
|     ], |     ], | ||||||
|     importmap = "k8s.io/kops/vendor/golang.org/x/sys/windows", |     importmap = "k8s.io/kops/vendor/golang.org/x/sys/windows", | ||||||
|  |  | ||||||
|  | @ -0,0 +1,64 @@ | ||||||
|  | #!/bin/bash | ||||||
|  | 
 | ||||||
|  | # 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. | ||||||
|  | 
 | ||||||
|  | set -e | ||||||
|  | shopt -s nullglob | ||||||
|  | 
 | ||||||
|  | [[ $# -eq 1 ]] || { echo "Usage: $0 OUTPUT_FILE.go" >&2; exit 1; } | ||||||
|  | winerror="$(printf '%s\n' "/mnt/c/Program Files (x86)/Windows Kits/"/*/Include/*/shared/winerror.h | sort -Vr | head -n 1)" | ||||||
|  | [[ -n $winerror ]] || { echo "Unable to find winerror.h" >&2; exit 1; } | ||||||
|  | 
 | ||||||
|  | declare -A errors | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  | 	echo "// Code generated by 'go generate'; DO NOT EDIT." | ||||||
|  | 	echo | ||||||
|  | 	echo "package windows" | ||||||
|  | 	echo "import \"syscall\"" | ||||||
|  | 	echo "const (" | ||||||
|  | 
 | ||||||
|  | 	while read -r line; do | ||||||
|  | 		unset vtype | ||||||
|  | 		if [[ $line =~ ^#define\ +([A-Z0-9_]+k?)\ +([A-Z0-9_]+\()?([A-Z][A-Z0-9_]+k?)\)? ]]; then | ||||||
|  | 			key="${BASH_REMATCH[1]}" | ||||||
|  | 			value="${BASH_REMATCH[3]}" | ||||||
|  | 		elif [[ $line =~ ^#define\ +([A-Z0-9_]+k?)\ +([A-Z0-9_]+\()?((0x)?[0-9A-Fa-f]+)L?\)? ]]; then | ||||||
|  | 			key="${BASH_REMATCH[1]}" | ||||||
|  | 			value="${BASH_REMATCH[3]}" | ||||||
|  | 			vtype="${BASH_REMATCH[2]}" | ||||||
|  | 		elif [[ $line =~ ^#define\ +([A-Z0-9_]+k?)\ +\(\(([A-Z]+)\)((0x)?[0-9A-Fa-f]+)L?\) ]]; then | ||||||
|  | 			key="${BASH_REMATCH[1]}" | ||||||
|  | 			value="${BASH_REMATCH[3]}" | ||||||
|  | 			vtype="${BASH_REMATCH[2]}" | ||||||
|  | 		else | ||||||
|  | 			continue | ||||||
|  | 		fi | ||||||
|  | 		[[ -n $key && -n $value ]] || continue | ||||||
|  | 		[[ -z ${errors["$key"]} ]] || continue | ||||||
|  | 		errors["$key"]="$value" | ||||||
|  | 		if [[ -v vtype ]]; then | ||||||
|  | 			if [[ $key == FACILITY_* || $key == NO_ERROR ]]; then | ||||||
|  | 				vtype="" | ||||||
|  | 			elif [[ $vtype == *HANDLE* || $vtype == *HRESULT* ]]; then | ||||||
|  | 				vtype="Handle" | ||||||
|  | 			else | ||||||
|  | 				vtype="syscall.Errno" | ||||||
|  | 			fi | ||||||
|  | 			last_vtype="$vtype" | ||||||
|  | 		else | ||||||
|  | 			vtype="" | ||||||
|  | 			if [[ $last_vtype == Handle && $value == NO_ERROR ]]; then | ||||||
|  | 				value="S_OK" | ||||||
|  | 			elif [[ $last_vtype == syscall.Errno && $value == NO_ERROR ]]; then | ||||||
|  | 				value="ERROR_SUCCESS" | ||||||
|  | 			fi | ||||||
|  | 		fi | ||||||
|  | 
 | ||||||
|  | 		echo "$key $vtype = $value" | ||||||
|  | 	done < "$winerror" | ||||||
|  | 
 | ||||||
|  | 	echo ")" | ||||||
|  | } | gofmt > "$1" | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | // 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.
 | ||||||
|  | 
 | ||||||
|  | package windows | ||||||
|  | 
 | ||||||
|  | //go:generate ./mkerrors.bash zerrors_windows.go
 | ||||||
|  | @ -169,6 +169,7 @@ const ( | ||||||
| //sys	GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
 | //sys	GetLengthSid(sid *SID) (len uint32) = advapi32.GetLengthSid
 | ||||||
| //sys	CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
 | //sys	CopySid(destSidLen uint32, destSid *SID, srcSid *SID) (err error) = advapi32.CopySid
 | ||||||
| //sys	AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) = advapi32.AllocateAndInitializeSid
 | //sys	AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, subAuth0 uint32, subAuth1 uint32, subAuth2 uint32, subAuth3 uint32, subAuth4 uint32, subAuth5 uint32, subAuth6 uint32, subAuth7 uint32, sid **SID) (err error) = advapi32.AllocateAndInitializeSid
 | ||||||
|  | //sys	createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) = advapi32.CreateWellKnownSid
 | ||||||
| //sys	FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
 | //sys	FreeSid(sid *SID) (err error) [failretval!=0] = advapi32.FreeSid
 | ||||||
| //sys	EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
 | //sys	EqualSid(sid1 *SID, sid2 *SID) (isEqual bool) = advapi32.EqualSid
 | ||||||
| 
 | 
 | ||||||
|  | @ -286,6 +287,158 @@ func (sid *SID) LookupAccount(system string) (account, domain string, accType ui | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Various types of pre-specified sids that can be synthesized at runtime.
 | ||||||
|  | type WELL_KNOWN_SID_TYPE uint32 | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	WinNullSid                                    = 0 | ||||||
|  | 	WinWorldSid                                   = 1 | ||||||
|  | 	WinLocalSid                                   = 2 | ||||||
|  | 	WinCreatorOwnerSid                            = 3 | ||||||
|  | 	WinCreatorGroupSid                            = 4 | ||||||
|  | 	WinCreatorOwnerServerSid                      = 5 | ||||||
|  | 	WinCreatorGroupServerSid                      = 6 | ||||||
|  | 	WinNtAuthoritySid                             = 7 | ||||||
|  | 	WinDialupSid                                  = 8 | ||||||
|  | 	WinNetworkSid                                 = 9 | ||||||
|  | 	WinBatchSid                                   = 10 | ||||||
|  | 	WinInteractiveSid                             = 11 | ||||||
|  | 	WinServiceSid                                 = 12 | ||||||
|  | 	WinAnonymousSid                               = 13 | ||||||
|  | 	WinProxySid                                   = 14 | ||||||
|  | 	WinEnterpriseControllersSid                   = 15 | ||||||
|  | 	WinSelfSid                                    = 16 | ||||||
|  | 	WinAuthenticatedUserSid                       = 17 | ||||||
|  | 	WinRestrictedCodeSid                          = 18 | ||||||
|  | 	WinTerminalServerSid                          = 19 | ||||||
|  | 	WinRemoteLogonIdSid                           = 20 | ||||||
|  | 	WinLogonIdsSid                                = 21 | ||||||
|  | 	WinLocalSystemSid                             = 22 | ||||||
|  | 	WinLocalServiceSid                            = 23 | ||||||
|  | 	WinNetworkServiceSid                          = 24 | ||||||
|  | 	WinBuiltinDomainSid                           = 25 | ||||||
|  | 	WinBuiltinAdministratorsSid                   = 26 | ||||||
|  | 	WinBuiltinUsersSid                            = 27 | ||||||
|  | 	WinBuiltinGuestsSid                           = 28 | ||||||
|  | 	WinBuiltinPowerUsersSid                       = 29 | ||||||
|  | 	WinBuiltinAccountOperatorsSid                 = 30 | ||||||
|  | 	WinBuiltinSystemOperatorsSid                  = 31 | ||||||
|  | 	WinBuiltinPrintOperatorsSid                   = 32 | ||||||
|  | 	WinBuiltinBackupOperatorsSid                  = 33 | ||||||
|  | 	WinBuiltinReplicatorSid                       = 34 | ||||||
|  | 	WinBuiltinPreWindows2000CompatibleAccessSid   = 35 | ||||||
|  | 	WinBuiltinRemoteDesktopUsersSid               = 36 | ||||||
|  | 	WinBuiltinNetworkConfigurationOperatorsSid    = 37 | ||||||
|  | 	WinAccountAdministratorSid                    = 38 | ||||||
|  | 	WinAccountGuestSid                            = 39 | ||||||
|  | 	WinAccountKrbtgtSid                           = 40 | ||||||
|  | 	WinAccountDomainAdminsSid                     = 41 | ||||||
|  | 	WinAccountDomainUsersSid                      = 42 | ||||||
|  | 	WinAccountDomainGuestsSid                     = 43 | ||||||
|  | 	WinAccountComputersSid                        = 44 | ||||||
|  | 	WinAccountControllersSid                      = 45 | ||||||
|  | 	WinAccountCertAdminsSid                       = 46 | ||||||
|  | 	WinAccountSchemaAdminsSid                     = 47 | ||||||
|  | 	WinAccountEnterpriseAdminsSid                 = 48 | ||||||
|  | 	WinAccountPolicyAdminsSid                     = 49 | ||||||
|  | 	WinAccountRasAndIasServersSid                 = 50 | ||||||
|  | 	WinNTLMAuthenticationSid                      = 51 | ||||||
|  | 	WinDigestAuthenticationSid                    = 52 | ||||||
|  | 	WinSChannelAuthenticationSid                  = 53 | ||||||
|  | 	WinThisOrganizationSid                        = 54 | ||||||
|  | 	WinOtherOrganizationSid                       = 55 | ||||||
|  | 	WinBuiltinIncomingForestTrustBuildersSid      = 56 | ||||||
|  | 	WinBuiltinPerfMonitoringUsersSid              = 57 | ||||||
|  | 	WinBuiltinPerfLoggingUsersSid                 = 58 | ||||||
|  | 	WinBuiltinAuthorizationAccessSid              = 59 | ||||||
|  | 	WinBuiltinTerminalServerLicenseServersSid     = 60 | ||||||
|  | 	WinBuiltinDCOMUsersSid                        = 61 | ||||||
|  | 	WinBuiltinIUsersSid                           = 62 | ||||||
|  | 	WinIUserSid                                   = 63 | ||||||
|  | 	WinBuiltinCryptoOperatorsSid                  = 64 | ||||||
|  | 	WinUntrustedLabelSid                          = 65 | ||||||
|  | 	WinLowLabelSid                                = 66 | ||||||
|  | 	WinMediumLabelSid                             = 67 | ||||||
|  | 	WinHighLabelSid                               = 68 | ||||||
|  | 	WinSystemLabelSid                             = 69 | ||||||
|  | 	WinWriteRestrictedCodeSid                     = 70 | ||||||
|  | 	WinCreatorOwnerRightsSid                      = 71 | ||||||
|  | 	WinCacheablePrincipalsGroupSid                = 72 | ||||||
|  | 	WinNonCacheablePrincipalsGroupSid             = 73 | ||||||
|  | 	WinEnterpriseReadonlyControllersSid           = 74 | ||||||
|  | 	WinAccountReadonlyControllersSid              = 75 | ||||||
|  | 	WinBuiltinEventLogReadersGroup                = 76 | ||||||
|  | 	WinNewEnterpriseReadonlyControllersSid        = 77 | ||||||
|  | 	WinBuiltinCertSvcDComAccessGroup              = 78 | ||||||
|  | 	WinMediumPlusLabelSid                         = 79 | ||||||
|  | 	WinLocalLogonSid                              = 80 | ||||||
|  | 	WinConsoleLogonSid                            = 81 | ||||||
|  | 	WinThisOrganizationCertificateSid             = 82 | ||||||
|  | 	WinApplicationPackageAuthoritySid             = 83 | ||||||
|  | 	WinBuiltinAnyPackageSid                       = 84 | ||||||
|  | 	WinCapabilityInternetClientSid                = 85 | ||||||
|  | 	WinCapabilityInternetClientServerSid          = 86 | ||||||
|  | 	WinCapabilityPrivateNetworkClientServerSid    = 87 | ||||||
|  | 	WinCapabilityPicturesLibrarySid               = 88 | ||||||
|  | 	WinCapabilityVideosLibrarySid                 = 89 | ||||||
|  | 	WinCapabilityMusicLibrarySid                  = 90 | ||||||
|  | 	WinCapabilityDocumentsLibrarySid              = 91 | ||||||
|  | 	WinCapabilitySharedUserCertificatesSid        = 92 | ||||||
|  | 	WinCapabilityEnterpriseAuthenticationSid      = 93 | ||||||
|  | 	WinCapabilityRemovableStorageSid              = 94 | ||||||
|  | 	WinBuiltinRDSRemoteAccessServersSid           = 95 | ||||||
|  | 	WinBuiltinRDSEndpointServersSid               = 96 | ||||||
|  | 	WinBuiltinRDSManagementServersSid             = 97 | ||||||
|  | 	WinUserModeDriversSid                         = 98 | ||||||
|  | 	WinBuiltinHyperVAdminsSid                     = 99 | ||||||
|  | 	WinAccountCloneableControllersSid             = 100 | ||||||
|  | 	WinBuiltinAccessControlAssistanceOperatorsSid = 101 | ||||||
|  | 	WinBuiltinRemoteManagementUsersSid            = 102 | ||||||
|  | 	WinAuthenticationAuthorityAssertedSid         = 103 | ||||||
|  | 	WinAuthenticationServiceAssertedSid           = 104 | ||||||
|  | 	WinLocalAccountSid                            = 105 | ||||||
|  | 	WinLocalAccountAndAdministratorSid            = 106 | ||||||
|  | 	WinAccountProtectedUsersSid                   = 107 | ||||||
|  | 	WinCapabilityAppointmentsSid                  = 108 | ||||||
|  | 	WinCapabilityContactsSid                      = 109 | ||||||
|  | 	WinAccountDefaultSystemManagedSid             = 110 | ||||||
|  | 	WinBuiltinDefaultSystemManagedGroupSid        = 111 | ||||||
|  | 	WinBuiltinStorageReplicaAdminsSid             = 112 | ||||||
|  | 	WinAccountKeyAdminsSid                        = 113 | ||||||
|  | 	WinAccountEnterpriseKeyAdminsSid              = 114 | ||||||
|  | 	WinAuthenticationKeyTrustSid                  = 115 | ||||||
|  | 	WinAuthenticationKeyPropertyMFASid            = 116 | ||||||
|  | 	WinAuthenticationKeyPropertyAttestationSid    = 117 | ||||||
|  | 	WinAuthenticationFreshKeyAuthSid              = 118 | ||||||
|  | 	WinBuiltinDeviceOwnersSid                     = 119 | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Creates a sid for a well-known predefined alias, generally using the constants of the form
 | ||||||
|  | // Win*Sid, for the local machine.
 | ||||||
|  | func CreateWellKnownSid(sidType WELL_KNOWN_SID_TYPE) (*SID, error) { | ||||||
|  | 	return CreateWellKnownDomainSid(sidType, nil) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Creates a sid for a well-known predefined alias, generally using the constants of the form
 | ||||||
|  | // Win*Sid, for the domain specified by the domainSid parameter.
 | ||||||
|  | func CreateWellKnownDomainSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID) (*SID, error) { | ||||||
|  | 	n := uint32(50) | ||||||
|  | 	for { | ||||||
|  | 		b := make([]byte, n) | ||||||
|  | 		sid := (*SID)(unsafe.Pointer(&b[0])) | ||||||
|  | 		err := createWellKnownSid(sidType, domainSid, sid, &n) | ||||||
|  | 		if err == nil { | ||||||
|  | 			return sid, nil | ||||||
|  | 		} | ||||||
|  | 		if err != ERROR_INSUFFICIENT_BUFFER { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 		if n <= uint32(len(b)) { | ||||||
|  | 			return nil, err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const ( | const ( | ||||||
| 	// do not reorder
 | 	// do not reorder
 | ||||||
| 	TOKEN_ASSIGN_PRIMARY = 1 << iota | 	TOKEN_ASSIGN_PRIMARY = 1 << iota | ||||||
|  |  | ||||||
|  | @ -99,8 +99,6 @@ const ( | ||||||
| 	SERVICE_CONFIG_DESCRIPTION     = 1 | 	SERVICE_CONFIG_DESCRIPTION     = 1 | ||||||
| 	SERVICE_CONFIG_FAILURE_ACTIONS = 2 | 	SERVICE_CONFIG_FAILURE_ACTIONS = 2 | ||||||
| 
 | 
 | ||||||
| 	NO_ERROR = 0 |  | ||||||
| 
 |  | ||||||
| 	SC_ENUM_PROCESS_INFO = 0 | 	SC_ENUM_PROCESS_INFO = 0 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -137,6 +137,7 @@ func NewCallbackCDecl(fn interface{}) uintptr { | ||||||
| //sys	CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
 | //sys	CreateFile(name *uint16, access uint32, mode uint32, sa *SecurityAttributes, createmode uint32, attrs uint32, templatefile int32) (handle Handle, err error) [failretval==InvalidHandle] = CreateFileW
 | ||||||
| //sys	ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
 | //sys	ReadFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
 | ||||||
| //sys	WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
 | //sys	WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) (err error)
 | ||||||
|  | //sys	GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error)
 | ||||||
| //sys	SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff]
 | //sys	SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) [failretval==0xffffffff]
 | ||||||
| //sys	CloseHandle(handle Handle) (err error)
 | //sys	CloseHandle(handle Handle) (err error)
 | ||||||
| //sys	GetStdHandle(stdhandle uint32) (handle Handle, err error) [failretval==InvalidHandle]
 | //sys	GetStdHandle(stdhandle uint32) (handle Handle, err error) [failretval==InvalidHandle]
 | ||||||
|  |  | ||||||
|  | @ -6,33 +6,6 @@ package windows | ||||||
| 
 | 
 | ||||||
| import "syscall" | import "syscall" | ||||||
| 
 | 
 | ||||||
| const ( |  | ||||||
| 	// Windows errors.
 |  | ||||||
| 	ERROR_FILE_NOT_FOUND         syscall.Errno = 2 |  | ||||||
| 	ERROR_PATH_NOT_FOUND         syscall.Errno = 3 |  | ||||||
| 	ERROR_ACCESS_DENIED          syscall.Errno = 5 |  | ||||||
| 	ERROR_NO_MORE_FILES          syscall.Errno = 18 |  | ||||||
| 	ERROR_HANDLE_EOF             syscall.Errno = 38 |  | ||||||
| 	ERROR_NETNAME_DELETED        syscall.Errno = 64 |  | ||||||
| 	ERROR_FILE_EXISTS            syscall.Errno = 80 |  | ||||||
| 	ERROR_BROKEN_PIPE            syscall.Errno = 109 |  | ||||||
| 	ERROR_BUFFER_OVERFLOW        syscall.Errno = 111 |  | ||||||
| 	ERROR_INSUFFICIENT_BUFFER    syscall.Errno = 122 |  | ||||||
| 	ERROR_MOD_NOT_FOUND          syscall.Errno = 126 |  | ||||||
| 	ERROR_PROC_NOT_FOUND         syscall.Errno = 127 |  | ||||||
| 	ERROR_ALREADY_EXISTS         syscall.Errno = 183 |  | ||||||
| 	ERROR_ENVVAR_NOT_FOUND       syscall.Errno = 203 |  | ||||||
| 	ERROR_MORE_DATA              syscall.Errno = 234 |  | ||||||
| 	ERROR_OPERATION_ABORTED      syscall.Errno = 995 |  | ||||||
| 	ERROR_IO_PENDING             syscall.Errno = 997 |  | ||||||
| 	ERROR_SERVICE_SPECIFIC_ERROR syscall.Errno = 1066 |  | ||||||
| 	ERROR_NOT_FOUND              syscall.Errno = 1168 |  | ||||||
| 	ERROR_PRIVILEGE_NOT_HELD     syscall.Errno = 1314 |  | ||||||
| 	WSAEACCES                    syscall.Errno = 10013 |  | ||||||
| 	WSAEMSGSIZE                  syscall.Errno = 10040 |  | ||||||
| 	WSAECONNRESET                syscall.Errno = 10054 |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| const ( | const ( | ||||||
| 	// Invented values to support what package os expects.
 | 	// Invented values to support what package os expects.
 | ||||||
| 	O_RDONLY   = 0x00000 | 	O_RDONLY   = 0x00000 | ||||||
|  | @ -126,9 +99,19 @@ const ( | ||||||
| 	OPEN_ALWAYS       = 4 | 	OPEN_ALWAYS       = 4 | ||||||
| 	TRUNCATE_EXISTING = 5 | 	TRUNCATE_EXISTING = 5 | ||||||
| 
 | 
 | ||||||
| 	FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000 | 	FILE_FLAG_OPEN_REQUIRING_OPLOCK = 0x00040000 | ||||||
| 	FILE_FLAG_BACKUP_SEMANTICS   = 0x02000000 | 	FILE_FLAG_FIRST_PIPE_INSTANCE   = 0x00080000 | ||||||
| 	FILE_FLAG_OVERLAPPED         = 0x40000000 | 	FILE_FLAG_OPEN_NO_RECALL        = 0x00100000 | ||||||
|  | 	FILE_FLAG_OPEN_REPARSE_POINT    = 0x00200000 | ||||||
|  | 	FILE_FLAG_SESSION_AWARE         = 0x00800000 | ||||||
|  | 	FILE_FLAG_POSIX_SEMANTICS       = 0x01000000 | ||||||
|  | 	FILE_FLAG_BACKUP_SEMANTICS      = 0x02000000 | ||||||
|  | 	FILE_FLAG_DELETE_ON_CLOSE       = 0x04000000 | ||||||
|  | 	FILE_FLAG_SEQUENTIAL_SCAN       = 0x08000000 | ||||||
|  | 	FILE_FLAG_RANDOM_ACCESS         = 0x10000000 | ||||||
|  | 	FILE_FLAG_NO_BUFFERING          = 0x20000000 | ||||||
|  | 	FILE_FLAG_OVERLAPPED            = 0x40000000 | ||||||
|  | 	FILE_FLAG_WRITE_THROUGH         = 0x80000000 | ||||||
| 
 | 
 | ||||||
| 	HANDLE_FLAG_INHERIT    = 0x00000001 | 	HANDLE_FLAG_INHERIT    = 0x00000001 | ||||||
| 	STARTF_USESTDHANDLES   = 0x00000100 | 	STARTF_USESTDHANDLES   = 0x00000100 | ||||||
|  | @ -167,7 +150,6 @@ const ( | ||||||
| 	IGNORE                = 0 | 	IGNORE                = 0 | ||||||
| 	INFINITE              = 0xffffffff | 	INFINITE              = 0xffffffff | ||||||
| 
 | 
 | ||||||
| 	WAIT_TIMEOUT   = 258 |  | ||||||
| 	WAIT_ABANDONED = 0x00000080 | 	WAIT_ABANDONED = 0x00000080 | ||||||
| 	WAIT_OBJECT_0  = 0x00000000 | 	WAIT_OBJECT_0  = 0x00000000 | ||||||
| 	WAIT_FAILED    = 0xFFFFFFFF | 	WAIT_FAILED    = 0xFFFFFFFF | ||||||
|  | @ -402,12 +384,6 @@ const ( | ||||||
| 	CERT_CHAIN_POLICY_EV                = 8 | 	CERT_CHAIN_POLICY_EV                = 8 | ||||||
| 	CERT_CHAIN_POLICY_SSL_F12           = 9 | 	CERT_CHAIN_POLICY_SSL_F12           = 9 | ||||||
| 
 | 
 | ||||||
| 	CERT_E_EXPIRED       = 0x800B0101 |  | ||||||
| 	CERT_E_ROLE          = 0x800B0103 |  | ||||||
| 	CERT_E_PURPOSE       = 0x800B0106 |  | ||||||
| 	CERT_E_UNTRUSTEDROOT = 0x800B0109 |  | ||||||
| 	CERT_E_CN_NO_MATCH   = 0x800B010F |  | ||||||
| 
 |  | ||||||
| 	/* AuthType values for SSLExtraCertChainPolicyPara struct */ | 	/* AuthType values for SSLExtraCertChainPolicyPara struct */ | ||||||
| 	AUTHTYPE_CLIENT = 1 | 	AUTHTYPE_CLIENT = 1 | ||||||
| 	AUTHTYPE_SERVER = 2 | 	AUTHTYPE_SERVER = 2 | ||||||
|  | @ -849,10 +825,6 @@ const ( | ||||||
| 	DNS_TYPE_NBSTAT  = 0xff01 | 	DNS_TYPE_NBSTAT  = 0xff01 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( |  | ||||||
| 	DNS_INFO_NO_RECORDS = 0x251D |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| const ( | const ( | ||||||
| 	// flags inside DNSRecord.Dw
 | 	// flags inside DNSRecord.Dw
 | ||||||
| 	DnsSectionQuestion   = 0x0000 | 	DnsSectionQuestion   = 0x0000 | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -77,6 +77,7 @@ var ( | ||||||
| 	procCreateFileW                        = modkernel32.NewProc("CreateFileW") | 	procCreateFileW                        = modkernel32.NewProc("CreateFileW") | ||||||
| 	procReadFile                           = modkernel32.NewProc("ReadFile") | 	procReadFile                           = modkernel32.NewProc("ReadFile") | ||||||
| 	procWriteFile                          = modkernel32.NewProc("WriteFile") | 	procWriteFile                          = modkernel32.NewProc("WriteFile") | ||||||
|  | 	procGetOverlappedResult                = modkernel32.NewProc("GetOverlappedResult") | ||||||
| 	procSetFilePointer                     = modkernel32.NewProc("SetFilePointer") | 	procSetFilePointer                     = modkernel32.NewProc("SetFilePointer") | ||||||
| 	procCloseHandle                        = modkernel32.NewProc("CloseHandle") | 	procCloseHandle                        = modkernel32.NewProc("CloseHandle") | ||||||
| 	procGetStdHandle                       = modkernel32.NewProc("GetStdHandle") | 	procGetStdHandle                       = modkernel32.NewProc("GetStdHandle") | ||||||
|  | @ -246,6 +247,7 @@ var ( | ||||||
| 	procGetLengthSid                       = modadvapi32.NewProc("GetLengthSid") | 	procGetLengthSid                       = modadvapi32.NewProc("GetLengthSid") | ||||||
| 	procCopySid                            = modadvapi32.NewProc("CopySid") | 	procCopySid                            = modadvapi32.NewProc("CopySid") | ||||||
| 	procAllocateAndInitializeSid           = modadvapi32.NewProc("AllocateAndInitializeSid") | 	procAllocateAndInitializeSid           = modadvapi32.NewProc("AllocateAndInitializeSid") | ||||||
|  | 	procCreateWellKnownSid                 = modadvapi32.NewProc("CreateWellKnownSid") | ||||||
| 	procFreeSid                            = modadvapi32.NewProc("FreeSid") | 	procFreeSid                            = modadvapi32.NewProc("FreeSid") | ||||||
| 	procEqualSid                           = modadvapi32.NewProc("EqualSid") | 	procEqualSid                           = modadvapi32.NewProc("EqualSid") | ||||||
| 	procCheckTokenMembership               = modadvapi32.NewProc("CheckTokenMembership") | 	procCheckTokenMembership               = modadvapi32.NewProc("CheckTokenMembership") | ||||||
|  | @ -653,6 +655,24 @@ func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped) | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func GetOverlappedResult(handle Handle, overlapped *Overlapped, done *uint32, wait bool) (err error) { | ||||||
|  | 	var _p0 uint32 | ||||||
|  | 	if wait { | ||||||
|  | 		_p0 = 1 | ||||||
|  | 	} else { | ||||||
|  | 		_p0 = 0 | ||||||
|  | 	} | ||||||
|  | 	r1, _, e1 := syscall.Syscall6(procGetOverlappedResult.Addr(), 4, uintptr(handle), uintptr(unsafe.Pointer(overlapped)), uintptr(unsafe.Pointer(done)), uintptr(_p0), 0, 0) | ||||||
|  | 	if r1 == 0 { | ||||||
|  | 		if e1 != 0 { | ||||||
|  | 			err = errnoErr(e1) | ||||||
|  | 		} else { | ||||||
|  | 			err = syscall.EINVAL | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { | func SetFilePointer(handle Handle, lowoffset int32, highoffsetptr *int32, whence uint32) (newlowoffset uint32, err error) { | ||||||
| 	r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) | 	r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0) | ||||||
| 	newlowoffset = uint32(r0) | 	newlowoffset = uint32(r0) | ||||||
|  | @ -2654,6 +2674,18 @@ func AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, s | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func createWellKnownSid(sidType WELL_KNOWN_SID_TYPE, domainSid *SID, sid *SID, sizeSid *uint32) (err error) { | ||||||
|  | 	r1, _, e1 := syscall.Syscall6(procCreateWellKnownSid.Addr(), 4, uintptr(sidType), uintptr(unsafe.Pointer(domainSid)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sizeSid)), 0, 0) | ||||||
|  | 	if r1 == 0 { | ||||||
|  | 		if e1 != 0 { | ||||||
|  | 			err = errnoErr(e1) | ||||||
|  | 		} else { | ||||||
|  | 			err = syscall.EINVAL | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func FreeSid(sid *SID) (err error) { | func FreeSid(sid *SID) (err error) { | ||||||
| 	r1, _, e1 := syscall.Syscall(procFreeSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) | 	r1, _, e1 := syscall.Syscall(procFreeSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 0) | ||||||
| 	if r1 != 0 { | 	if r1 != 0 { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | load("@io_bazel_rules_go//go:def.bzl", "go_library") | ||||||
|  | 
 | ||||||
|  | go_library( | ||||||
|  |     name = "go_default_library", | ||||||
|  |     srcs = [ | ||||||
|  |         "analysis.go", | ||||||
|  |         "diagnostic.go", | ||||||
|  |         "doc.go", | ||||||
|  |         "validate.go", | ||||||
|  |     ], | ||||||
|  |     importmap = "k8s.io/kops/vendor/golang.org/x/tools/go/analysis", | ||||||
|  |     importpath = "golang.org/x/tools/go/analysis", | ||||||
|  |     visibility = ["//visibility:public"], | ||||||
|  | ) | ||||||
|  | @ -0,0 +1,213 @@ | ||||||
|  | package analysis | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"go/ast" | ||||||
|  | 	"go/token" | ||||||
|  | 	"go/types" | ||||||
|  | 	"reflect" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // An Analyzer describes an analysis function and its options.
 | ||||||
|  | type Analyzer struct { | ||||||
|  | 	// The Name of the analyzer must be a valid Go identifier
 | ||||||
|  | 	// as it may appear in command-line flags, URLs, and so on.
 | ||||||
|  | 	Name string | ||||||
|  | 
 | ||||||
|  | 	// Doc is the documentation for the analyzer.
 | ||||||
|  | 	// The part before the first "\n\n" is the title
 | ||||||
|  | 	// (no capital or period, max ~60 letters).
 | ||||||
|  | 	Doc string | ||||||
|  | 
 | ||||||
|  | 	// Flags defines any flags accepted by the analyzer.
 | ||||||
|  | 	// The manner in which these flags are exposed to the user
 | ||||||
|  | 	// depends on the driver which runs the analyzer.
 | ||||||
|  | 	Flags flag.FlagSet | ||||||
|  | 
 | ||||||
|  | 	// Run applies the analyzer to a package.
 | ||||||
|  | 	// It returns an error if the analyzer failed.
 | ||||||
|  | 	//
 | ||||||
|  | 	// On success, the Run function may return a result
 | ||||||
|  | 	// computed by the Analyzer; its type must match ResultType.
 | ||||||
|  | 	// The driver makes this result available as an input to
 | ||||||
|  | 	// another Analyzer that depends directly on this one (see
 | ||||||
|  | 	// Requires) when it analyzes the same package.
 | ||||||
|  | 	//
 | ||||||
|  | 	// To pass analysis results between packages (and thus
 | ||||||
|  | 	// potentially between address spaces), use Facts, which are
 | ||||||
|  | 	// serializable.
 | ||||||
|  | 	Run func(*Pass) (interface{}, error) | ||||||
|  | 
 | ||||||
|  | 	// RunDespiteErrors allows the driver to invoke
 | ||||||
|  | 	// the Run method of this analyzer even on a
 | ||||||
|  | 	// package that contains parse or type errors.
 | ||||||
|  | 	RunDespiteErrors bool | ||||||
|  | 
 | ||||||
|  | 	// Requires is a set of analyzers that must run successfully
 | ||||||
|  | 	// before this one on a given package. This analyzer may inspect
 | ||||||
|  | 	// the outputs produced by each analyzer in Requires.
 | ||||||
|  | 	// The graph over analyzers implied by Requires edges must be acyclic.
 | ||||||
|  | 	//
 | ||||||
|  | 	// Requires establishes a "horizontal" dependency between
 | ||||||
|  | 	// analysis passes (different analyzers, same package).
 | ||||||
|  | 	Requires []*Analyzer | ||||||
|  | 
 | ||||||
|  | 	// ResultType is the type of the optional result of the Run function.
 | ||||||
|  | 	ResultType reflect.Type | ||||||
|  | 
 | ||||||
|  | 	// FactTypes indicates that this analyzer imports and exports
 | ||||||
|  | 	// Facts of the specified concrete types.
 | ||||||
|  | 	// An analyzer that uses facts may assume that its import
 | ||||||
|  | 	// dependencies have been similarly analyzed before it runs.
 | ||||||
|  | 	// Facts must be pointers.
 | ||||||
|  | 	//
 | ||||||
|  | 	// FactTypes establishes a "vertical" dependency between
 | ||||||
|  | 	// analysis passes (same analyzer, different packages).
 | ||||||
|  | 	FactTypes []Fact | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (a *Analyzer) String() string { return a.Name } | ||||||
|  | 
 | ||||||
|  | // A Pass provides information to the Run function that
 | ||||||
|  | // applies a specific analyzer to a single Go package.
 | ||||||
|  | //
 | ||||||
|  | // It forms the interface between the analysis logic and the driver
 | ||||||
|  | // program, and has both input and an output components.
 | ||||||
|  | //
 | ||||||
|  | // As in a compiler, one pass may depend on the result computed by another.
 | ||||||
|  | //
 | ||||||
|  | // The Run function should not call any of the Pass functions concurrently.
 | ||||||
|  | type Pass struct { | ||||||
|  | 	Analyzer *Analyzer // the identity of the current analyzer
 | ||||||
|  | 
 | ||||||
|  | 	// syntax and type information
 | ||||||
|  | 	Fset       *token.FileSet // file position information
 | ||||||
|  | 	Files      []*ast.File    // the abstract syntax tree of each file
 | ||||||
|  | 	OtherFiles []string       // names of non-Go files of this package
 | ||||||
|  | 	Pkg        *types.Package // type information about the package
 | ||||||
|  | 	TypesInfo  *types.Info    // type information about the syntax trees
 | ||||||
|  | 	TypesSizes types.Sizes    // function for computing sizes of types
 | ||||||
|  | 
 | ||||||
|  | 	// Report reports a Diagnostic, a finding about a specific location
 | ||||||
|  | 	// in the analyzed source code such as a potential mistake.
 | ||||||
|  | 	// It may be called by the Run function.
 | ||||||
|  | 	Report func(Diagnostic) | ||||||
|  | 
 | ||||||
|  | 	// ResultOf provides the inputs to this analysis pass, which are
 | ||||||
|  | 	// the corresponding results of its prerequisite analyzers.
 | ||||||
|  | 	// The map keys are the elements of Analysis.Required,
 | ||||||
|  | 	// and the type of each corresponding value is the required
 | ||||||
|  | 	// analysis's ResultType.
 | ||||||
|  | 	ResultOf map[*Analyzer]interface{} | ||||||
|  | 
 | ||||||
|  | 	// -- facts --
 | ||||||
|  | 
 | ||||||
|  | 	// ImportObjectFact retrieves a fact associated with obj.
 | ||||||
|  | 	// Given a value ptr of type *T, where *T satisfies Fact,
 | ||||||
|  | 	// ImportObjectFact copies the value to *ptr.
 | ||||||
|  | 	//
 | ||||||
|  | 	// ImportObjectFact panics if called after the pass is complete.
 | ||||||
|  | 	// ImportObjectFact is not concurrency-safe.
 | ||||||
|  | 	ImportObjectFact func(obj types.Object, fact Fact) bool | ||||||
|  | 
 | ||||||
|  | 	// ImportPackageFact retrieves a fact associated with package pkg,
 | ||||||
|  | 	// which must be this package or one of its dependencies.
 | ||||||
|  | 	// See comments for ImportObjectFact.
 | ||||||
|  | 	ImportPackageFact func(pkg *types.Package, fact Fact) bool | ||||||
|  | 
 | ||||||
|  | 	// ExportObjectFact associates a fact of type *T with the obj,
 | ||||||
|  | 	// replacing any previous fact of that type.
 | ||||||
|  | 	//
 | ||||||
|  | 	// ExportObjectFact panics if it is called after the pass is
 | ||||||
|  | 	// complete, or if obj does not belong to the package being analyzed.
 | ||||||
|  | 	// ExportObjectFact is not concurrency-safe.
 | ||||||
|  | 	ExportObjectFact func(obj types.Object, fact Fact) | ||||||
|  | 
 | ||||||
|  | 	// ExportPackageFact associates a fact with the current package.
 | ||||||
|  | 	// See comments for ExportObjectFact.
 | ||||||
|  | 	ExportPackageFact func(fact Fact) | ||||||
|  | 
 | ||||||
|  | 	// AllPackageFacts returns a new slice containing all package facts in unspecified order.
 | ||||||
|  | 	// WARNING: This is an experimental API and may change in the future.
 | ||||||
|  | 	AllPackageFacts func() []PackageFact | ||||||
|  | 
 | ||||||
|  | 	// AllObjectFacts returns a new slice containing all object facts in unspecified order.
 | ||||||
|  | 	// WARNING: This is an experimental API and may change in the future.
 | ||||||
|  | 	AllObjectFacts func() []ObjectFact | ||||||
|  | 
 | ||||||
|  | 	/* Further fields may be added in future. */ | ||||||
|  | 	// For example, suggested or applied refactorings.
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // PackageFact is a package together with an associated fact.
 | ||||||
|  | // WARNING: This is an experimental API and may change in the future.
 | ||||||
|  | type PackageFact struct { | ||||||
|  | 	Package *types.Package | ||||||
|  | 	Fact    Fact | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ObjectFact is an object together with an associated fact.
 | ||||||
|  | // WARNING: This is an experimental API and may change in the future.
 | ||||||
|  | type ObjectFact struct { | ||||||
|  | 	Object types.Object | ||||||
|  | 	Fact   Fact | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Reportf is a helper function that reports a Diagnostic using the
 | ||||||
|  | // specified position and formatted error message.
 | ||||||
|  | func (pass *Pass) Reportf(pos token.Pos, format string, args ...interface{}) { | ||||||
|  | 	msg := fmt.Sprintf(format, args...) | ||||||
|  | 	pass.Report(Diagnostic{Pos: pos, Message: msg}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // reportNodef is a helper function that reports a Diagnostic using the
 | ||||||
|  | // range denoted by the AST node.
 | ||||||
|  | //
 | ||||||
|  | // WARNING: This is an experimental API and may change in the future.
 | ||||||
|  | func (pass *Pass) reportNodef(node ast.Node, format string, args ...interface{}) { | ||||||
|  | 	msg := fmt.Sprintf(format, args...) | ||||||
|  | 	pass.Report(Diagnostic{Pos: node.Pos(), End: node.End(), Message: msg}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (pass *Pass) String() string { | ||||||
|  | 	return fmt.Sprintf("%s@%s", pass.Analyzer.Name, pass.Pkg.Path()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // A Fact is an intermediate fact produced during analysis.
 | ||||||
|  | //
 | ||||||
|  | // Each fact is associated with a named declaration (a types.Object) or
 | ||||||
|  | // with a package as a whole. A single object or package may have
 | ||||||
|  | // multiple associated facts, but only one of any particular fact type.
 | ||||||
|  | //
 | ||||||
|  | // A Fact represents a predicate such as "never returns", but does not
 | ||||||
|  | // represent the subject of the predicate such as "function F" or "package P".
 | ||||||
|  | //
 | ||||||
|  | // Facts may be produced in one analysis pass and consumed by another
 | ||||||
|  | // analysis pass even if these are in different address spaces.
 | ||||||
|  | // If package P imports Q, all facts about Q produced during
 | ||||||
|  | // analysis of that package will be available during later analysis of P.
 | ||||||
|  | // Facts are analogous to type export data in a build system:
 | ||||||
|  | // just as export data enables separate compilation of several passes,
 | ||||||
|  | // facts enable "separate analysis".
 | ||||||
|  | //
 | ||||||
|  | // Each pass (a, p) starts with the set of facts produced by the
 | ||||||
|  | // same analyzer a applied to the packages directly imported by p.
 | ||||||
|  | // The analysis may add facts to the set, and they may be exported in turn.
 | ||||||
|  | // An analysis's Run function may retrieve facts by calling
 | ||||||
|  | // Pass.Import{Object,Package}Fact and update them using
 | ||||||
|  | // Pass.Export{Object,Package}Fact.
 | ||||||
|  | //
 | ||||||
|  | // A fact is logically private to its Analysis. To pass values
 | ||||||
|  | // between different analyzers, use the results mechanism;
 | ||||||
|  | // see Analyzer.Requires, Analyzer.ResultType, and Pass.ResultOf.
 | ||||||
|  | //
 | ||||||
|  | // A Fact type must be a pointer.
 | ||||||
|  | // Facts are encoded and decoded using encoding/gob.
 | ||||||
|  | // A Fact may implement the GobEncoder/GobDecoder interfaces
 | ||||||
|  | // to customize its encoding. Fact encoding should not fail.
 | ||||||
|  | //
 | ||||||
|  | // A Fact should not be modified once exported.
 | ||||||
|  | type Fact interface { | ||||||
|  | 	AFact() // dummy method to avoid type errors
 | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue