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/weaveworks/mesh v0.0.0-20170419100114-1f158d31de55
|
||||
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/oauth2 v0.0.0-20190402181905-9f3314589c9a
|
||||
google.golang.org/api v0.0.0-20181220000619-583d854617af
|
||||
gopkg.in/gcfg.v1 v1.2.0
|
||||
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/apimachinery 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/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/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.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s=
|
||||
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/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/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/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
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/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/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/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=
|
||||
|
|
@ -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-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-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-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
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/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-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-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-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/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
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-20190312061237-fead79001313 h1:pczuHS43Cp2ktBEEmLwScxgjWsBSzdaQiKzUyf3DTTc=
|
||||
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.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=
|
||||
|
|
@ -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-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-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/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU=
|
||||
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 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/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/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
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=
|
||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||
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/go.mod h1:AOxZTnaXR/xiarlQL0JUfwQPxjmKDvVYoRp58cA7lUo=
|
||||
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/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 = [
|
||||
"clone.go",
|
||||
"decode.go",
|
||||
"deprecated.go",
|
||||
"discard.go",
|
||||
"encode.go",
|
||||
"equal.go",
|
||||
|
|
|
|||
|
|
@ -186,7 +186,6 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
|
|||
if b&0x80 == 0 {
|
||||
goto done
|
||||
}
|
||||
// x -= 0x80 << 63 // Always zero.
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
m1, m2 := e1.value, e2.value
|
||||
m1 := extensionAsLegacyType(e1.value)
|
||||
m2 := extensionAsLegacyType(e2.value)
|
||||
|
||||
if m1 == nil && m2 == nil {
|
||||
// Both have only encoded form.
|
||||
|
|
|
|||
|
|
@ -185,9 +185,25 @@ type Extension struct {
|
|||
// extension will have only enc set. When such an extension is
|
||||
// accessed using GetExtension (or GetExtensions) desc and value
|
||||
// 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{}
|
||||
enc []byte
|
||||
|
||||
// enc is the raw bytes for the extension field.
|
||||
enc []byte
|
||||
}
|
||||
|
||||
// SetRawExtension is for testing only.
|
||||
|
|
@ -334,7 +350,7 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
|
|||
// descriptors with the same field number.
|
||||
return nil, errors.New("proto: descriptor conflict")
|
||||
}
|
||||
return e.value, nil
|
||||
return extensionAsLegacyType(e.value), 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.
|
||||
// That way it is safe to mutate what we return.
|
||||
e.value = v
|
||||
e.value = extensionAsStorageType(v)
|
||||
e.desc = extension
|
||||
e.enc = nil
|
||||
emap[extension.Field] = e
|
||||
return e.value, nil
|
||||
return extensionAsLegacyType(e.value), nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
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
|
||||
// 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[extension.Field] = Extension{desc: extension, value: value}
|
||||
extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -541,3 +557,51 @@ func RegisterExtension(desc *ExtensionDesc) {
|
|||
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
|
||||
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()
|
||||
}
|
||||
|
||||
// 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
|
||||
// protocol buffers. It may be reused between invocations to
|
||||
// reduce memory usage. It is not necessary to use a Buffer;
|
||||
|
|
@ -960,13 +940,19 @@ func isProto3Zero(v reflect.Value) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
const ProtoPackageIsVersion2 = true
|
||||
const (
|
||||
// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
ProtoPackageIsVersion3 = true
|
||||
|
||||
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
const ProtoPackageIsVersion1 = true
|
||||
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
|
||||
// to assert that that code is compatible with this version of the proto package.
|
||||
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.
|
||||
// This type is not intended to be used by non-generated code.
|
||||
|
|
|
|||
|
|
@ -36,13 +36,7 @@ package proto
|
|||
*/
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 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:]
|
||||
}
|
||||
|
||||
// MarshalMessageSet encodes the extension map represented by m 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.
|
||||
// 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.
|
||||
func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
||||
func unmarshalMessageSet(buf []byte, exts interface{}) error {
|
||||
var m map[int32]Extension
|
||||
switch exts := exts.(type) {
|
||||
case *XXX_InternalExtensions:
|
||||
|
|
@ -222,93 +179,3 @@ func UnmarshalMessageSet(buf []byte, exts interface{}) error {
|
|||
}
|
||||
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
|
||||
// the interface data.
|
||||
func toAddrPointer(i *interface{}, isptr bool) pointer {
|
||||
func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
|
||||
v := reflect.ValueOf(*i)
|
||||
u := reflect.New(v.Type())
|
||||
u.Elem().Set(v)
|
||||
if deref {
|
||||
u = u.Elem()
|
||||
}
|
||||
return pointer{v: u}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,16 +85,21 @@ func toPointer(i *Message) pointer {
|
|||
|
||||
// toAddrPointer converts an interface to a pointer that points to
|
||||
// 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.
|
||||
if isptr {
|
||||
// The interface is of pointer type, thus it is a direct interface.
|
||||
// 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
|
||||
// to the data.
|
||||
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
|
||||
if deref {
|
||||
p.p = *(*unsafe.Pointer)(p.p)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// valToPointer converts v to a pointer. v must be of pointer type.
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ package proto
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
|
@ -194,7 +193,7 @@ func (p *Properties) Parse(s string) {
|
|||
// "bytes,49,opt,name=foo,def=hello!"
|
||||
fields := strings.Split(s, ",") // breaks def=, but handled below.
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +213,7 @@ func (p *Properties) Parse(s string) {
|
|||
p.WireType = WireBytes
|
||||
// no numeric converter for non-numeric types
|
||||
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
|
||||
}
|
||||
|
||||
|
|
@ -334,9 +333,6 @@ func GetProperties(t reflect.Type) *StructProperties {
|
|||
sprop, ok := propertiesMap[t]
|
||||
propertiesMu.RUnlock()
|
||||
if ok {
|
||||
if collectStats {
|
||||
stats.Chit++
|
||||
}
|
||||
return sprop
|
||||
}
|
||||
|
||||
|
|
@ -346,17 +342,20 @@ func GetProperties(t reflect.Type) *StructProperties {
|
|||
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.
|
||||
func getPropertiesLocked(t reflect.Type) *StructProperties {
|
||||
if prop, ok := propertiesMap[t]; ok {
|
||||
if collectStats {
|
||||
stats.Chit++
|
||||
}
|
||||
return prop
|
||||
}
|
||||
if collectStats {
|
||||
stats.Cmiss++
|
||||
}
|
||||
|
||||
prop := new(StructProperties)
|
||||
// in case of recursive protos, fill this in now.
|
||||
|
|
@ -391,13 +390,14 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
|
|||
// Re-order prop.order.
|
||||
sort.Sort(prop)
|
||||
|
||||
type oneofMessage interface {
|
||||
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
|
||||
var oots []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 {
|
||||
var oots []interface{}
|
||||
_, _, _, oots = om.XXX_OneofFuncs()
|
||||
|
||||
if len(oots) > 0 {
|
||||
// Interpret oneof metadata.
|
||||
prop.OneofTypes = make(map[string]*OneofProperties)
|
||||
for _, oot := range oots {
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ type marshalElemInfo struct {
|
|||
sizer sizer
|
||||
marshaler marshaler
|
||||
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 (
|
||||
|
|
@ -320,8 +321,11 @@ func (u *marshalInfo) computeMarshalInfo() {
|
|||
|
||||
// get oneof implementers
|
||||
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()
|
||||
case oneofWrappersIface:
|
||||
oneofImplementers = m.XXX_OneofWrappers()
|
||||
}
|
||||
|
||||
n := t.NumField()
|
||||
|
|
@ -407,13 +411,22 @@ func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
|
|||
panic("tag is not an integer")
|
||||
}
|
||||
wt := wiretype(tags[0])
|
||||
if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct {
|
||||
t = t.Elem()
|
||||
}
|
||||
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{
|
||||
wiretag: uint64(tag)<<3 | wt,
|
||||
tagsize: SizeVarint(uint64(tag) << 3),
|
||||
sizer: sizer,
|
||||
marshaler: marshaler,
|
||||
isptr: t.Kind() == reflect.Ptr,
|
||||
deref: deref,
|
||||
}
|
||||
|
||||
// update cache
|
||||
|
|
@ -448,7 +461,7 @@ func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
|
|||
|
||||
func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
|
||||
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.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
|
||||
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.
|
||||
func wiretype(encoding string) uint64 {
|
||||
switch encoding {
|
||||
|
|
@ -2310,8 +2319,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
|
|||
for _, k := range m.MapKeys() {
|
||||
ki := k.Interface()
|
||||
vi := m.MapIndex(k).Interface()
|
||||
kaddr := toAddrPointer(&ki, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
|
||||
kaddr := toAddrPointer(&ki, false, false) // pointer to key
|
||||
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)
|
||||
n += siz + SizeVarint(uint64(siz)) + tagsize
|
||||
}
|
||||
|
|
@ -2329,8 +2338,8 @@ func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
|
|||
for _, k := range keys {
|
||||
ki := k.Interface()
|
||||
vi := m.MapIndex(k).Interface()
|
||||
kaddr := toAddrPointer(&ki, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr) // pointer to value
|
||||
kaddr := toAddrPointer(&ki, false, false) // pointer to key
|
||||
vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
|
||||
b = appendVarint(b, tag)
|
||||
siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
|
||||
b = appendVarint(b, uint64(siz))
|
||||
|
|
@ -2399,7 +2408,7 @@ func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
|
|||
// the last time this function was called.
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
n += ei.sizer(p, ei.tagsize)
|
||||
}
|
||||
mu.Unlock()
|
||||
|
|
@ -2434,7 +2443,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
|
|
@ -2465,7 +2474,7 @@ func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, de
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
|
|
@ -2510,7 +2519,7 @@ func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
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)
|
||||
}
|
||||
mu.Unlock()
|
||||
|
|
@ -2553,7 +2562,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
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)
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
|
|
@ -2591,7 +2600,7 @@ func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, de
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
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 = append(b, 1<<3|WireEndGroup)
|
||||
if !nerr.Merge(err) {
|
||||
|
|
@ -2621,7 +2630,7 @@ func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
n += ei.sizer(p, ei.tagsize)
|
||||
}
|
||||
return n
|
||||
|
|
@ -2656,7 +2665,7 @@ func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, determ
|
|||
|
||||
ei := u.getExtElemInfo(e.desc)
|
||||
v := e.value
|
||||
p := toAddrPointer(&v, ei.isptr)
|
||||
p := toAddrPointer(&v, ei.isptr, ei.deref)
|
||||
b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
|
||||
if !nerr.Merge(err) {
|
||||
return b, err
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
|
|||
u.computeUnmarshalInfo()
|
||||
}
|
||||
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 errLater error
|
||||
|
|
@ -362,46 +362,48 @@ func (u *unmarshalInfo) computeUnmarshalInfo() {
|
|||
}
|
||||
|
||||
// Find any types associated with oneof fields.
|
||||
// TODO: XXX_OneofFuncs returns more info than we need. Get rid of some of it?
|
||||
fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("XXX_OneofFuncs")
|
||||
if fn.IsValid() {
|
||||
res := fn.Call(nil)[3] // last return value from XXX_OneofFuncs: []interface{}
|
||||
for i := res.Len() - 1; i >= 0; i-- {
|
||||
v := res.Index(i) // interface{}
|
||||
tptr := reflect.ValueOf(v.Interface()).Type() // *Msg_X
|
||||
typ := tptr.Elem() // Msg_X
|
||||
var oneofImplementers []interface{}
|
||||
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
|
||||
case oneofFuncsIface:
|
||||
_, _, _, oneofImplementers = m.XXX_OneofFuncs()
|
||||
case oneofWrappersIface:
|
||||
oneofImplementers = m.XXX_OneofWrappers()
|
||||
}
|
||||
for _, v := range oneofImplementers {
|
||||
tptr := reflect.TypeOf(v) // *Msg_X
|
||||
typ := tptr.Elem() // Msg_X
|
||||
|
||||
f := typ.Field(0) // oneof implementers have one field
|
||||
baseUnmarshal := fieldUnmarshaler(&f)
|
||||
tags := strings.Split(f.Tag.Get("protobuf"), ",")
|
||||
fieldNum, err := strconv.Atoi(tags[1])
|
||||
if err != nil {
|
||||
panic("protobuf tag field not an integer: " + tags[1])
|
||||
}
|
||||
var name string
|
||||
for _, tag := range tags {
|
||||
if strings.HasPrefix(tag, "name=") {
|
||||
name = strings.TrimPrefix(tag, "name=")
|
||||
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)
|
||||
}
|
||||
f := typ.Field(0) // oneof implementers have one field
|
||||
baseUnmarshal := fieldUnmarshaler(&f)
|
||||
tags := strings.Split(f.Tag.Get("protobuf"), ",")
|
||||
fieldNum, err := strconv.Atoi(tags[1])
|
||||
if err != nil {
|
||||
panic("protobuf tag field not an integer: " + tags[1])
|
||||
}
|
||||
var name string
|
||||
for _, tag := range tags {
|
||||
if strings.HasPrefix(tag, "name=") {
|
||||
name = strings.TrimPrefix(tag, "name=")
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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 !u.extensions.IsValid() && !u.oldExtensions.IsValid() {
|
||||
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.
|
||||
func decodeVarint(b []byte) (uint64, int) {
|
||||
var x, y uint64
|
||||
if len(b) <= 0 {
|
||||
if len(b) == 0 {
|
||||
goto bad
|
||||
}
|
||||
x = uint64(b[0])
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: google/protobuf/any.proto
|
||||
|
||||
package any // import "github.com/golang/protobuf/ptypes/any"
|
||||
package any
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
@ -16,7 +18,7 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// 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
|
||||
// URL that describes the type of the serialized message.
|
||||
|
|
@ -99,17 +101,18 @@ const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
|||
// }
|
||||
//
|
||||
type Any struct {
|
||||
// A URL/resource name whose content describes the type of the
|
||||
// serialized protocol buffer message.
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// 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
|
||||
// following restrictions and interpretations apply:
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// 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.
|
||||
// * 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][]
|
||||
// value in binary format, or produce an error.
|
||||
// * 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
|
||||
// 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
|
||||
// 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 (*Any) ProtoMessage() {}
|
||||
func (*Any) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_any_744b9ca530f228db, []int{0}
|
||||
return fileDescriptor_b53526c13ae22eb4, []int{0}
|
||||
}
|
||||
|
||||
func (*Any) XXX_WellKnownType() string { return "Any" }
|
||||
|
||||
func (m *Any) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Any.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Any.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Any) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Any.Merge(dst, src)
|
||||
func (m *Any) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Any.Merge(m, src)
|
||||
}
|
||||
func (m *Any) XXX_Size() int {
|
||||
return xxx_messageInfo_Any.Size(m)
|
||||
|
|
@ -172,9 +181,9 @@ func init() {
|
|||
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
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -120,17 +120,18 @@ option objc_class_prefix = "GPB";
|
|||
// }
|
||||
//
|
||||
message Any {
|
||||
// A URL/resource name whose content describes the type of the
|
||||
// serialized protocol buffer message.
|
||||
// A URL/resource name that uniquely identifies the type of the serialized
|
||||
// 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
|
||||
// following restrictions and interpretations apply:
|
||||
// In practice, teams usually precompile into the binary all types that they
|
||||
// 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.
|
||||
// * 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][]
|
||||
// value in binary format, or produce an error.
|
||||
// * 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
|
||||
// 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
|
||||
// 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)
|
||||
}
|
||||
if p.Nanos != 0 {
|
||||
d += time.Duration(p.Nanos)
|
||||
d += time.Duration(p.Nanos) * time.Nanosecond
|
||||
if (d < 0) != (p.Nanos < 0) {
|
||||
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.
|
||||
// source: google/protobuf/duration.proto
|
||||
|
||||
package duration // import "github.com/golang/protobuf/ptypes/duration"
|
||||
package duration
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
@ -16,7 +18,7 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// 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
|
||||
// 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 (*Duration) ProtoMessage() {}
|
||||
func (*Duration) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_duration_e7d612259e3f0613, []int{0}
|
||||
return fileDescriptor_23597b2ebd7ac6c5, []int{0}
|
||||
}
|
||||
|
||||
func (*Duration) XXX_WellKnownType() string { return "Duration" }
|
||||
|
||||
func (m *Duration) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Duration.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Duration.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Duration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Duration.Merge(dst, src)
|
||||
func (m *Duration) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Duration.Merge(m, src)
|
||||
}
|
||||
func (m *Duration) XXX_Size() int {
|
||||
return xxx_messageInfo_Duration.Size(m)
|
||||
|
|
@ -138,11 +142,9 @@ func init() {
|
|||
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_duration_e7d612259e3f0613)
|
||||
}
|
||||
func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5) }
|
||||
|
||||
var fileDescriptor_duration_e7d612259e3f0613 = []byte{
|
||||
var fileDescriptor_23597b2ebd7ac6c5 = []byte{
|
||||
// 190 bytes of a gzipped FileDescriptorProto
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -111,11 +111,9 @@ func TimestampNow() *tspb.Timestamp {
|
|||
// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
|
||||
// It returns an error if the resulting Timestamp is invalid.
|
||||
func TimestampProto(t time.Time) (*tspb.Timestamp, error) {
|
||||
seconds := t.Unix()
|
||||
nanos := int32(t.Sub(time.Unix(seconds, 0)))
|
||||
ts := &tspb.Timestamp{
|
||||
Seconds: seconds,
|
||||
Nanos: nanos,
|
||||
Seconds: t.Unix(),
|
||||
Nanos: int32(t.Nanosecond()),
|
||||
}
|
||||
if err := validateTimestamp(ts); err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// source: google/protobuf/timestamp.proto
|
||||
|
||||
package timestamp // import "github.com/golang/protobuf/ptypes/timestamp"
|
||||
package timestamp
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
@ -16,7 +18,7 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// 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)
|
||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||
// can use the Joda Time's [`ISODateTimeFormat.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.
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
type Timestamp struct {
|
||||
|
|
@ -115,17 +119,19 @@ func (m *Timestamp) Reset() { *m = Timestamp{} }
|
|||
func (m *Timestamp) String() string { return proto.CompactTextString(m) }
|
||||
func (*Timestamp) ProtoMessage() {}
|
||||
func (*Timestamp) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_timestamp_b826e8e5fba671a8, []int{0}
|
||||
return fileDescriptor_292007bbfe81227e, []int{0}
|
||||
}
|
||||
|
||||
func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
|
||||
|
||||
func (m *Timestamp) XXX_Unmarshal(b []byte) error {
|
||||
return xxx_messageInfo_Timestamp.Unmarshal(m, b)
|
||||
}
|
||||
func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic)
|
||||
}
|
||||
func (dst *Timestamp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Timestamp.Merge(dst, src)
|
||||
func (m *Timestamp) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_Timestamp.Merge(m, src)
|
||||
}
|
||||
func (m *Timestamp) XXX_Size() int {
|
||||
return xxx_messageInfo_Timestamp.Size(m)
|
||||
|
|
@ -154,11 +160,9 @@ func init() {
|
|||
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_timestamp_b826e8e5fba671a8)
|
||||
}
|
||||
func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e) }
|
||||
|
||||
var fileDescriptor_timestamp_b826e8e5fba671a8 = []byte{
|
||||
var fileDescriptor_292007bbfe81227e = []byte{
|
||||
// 191 bytes of a gzipped FileDescriptorProto
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -103,7 +103,9 @@ option objc_class_prefix = "GPB";
|
|||
// {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),
|
||||
// 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
|
||||
// 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)
|
||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
||||
// can use the Joda Time's [`ISODateTimeFormat.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.
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
message Timestamp {
|
||||
|
|
|
|||
|
|
@ -7105,15 +7105,15 @@ func (m *Any) ToRawInfo() interface{} {
|
|||
// ToRawInfo returns a description of ApiKeySecurity suitable for JSON or YAML export.
|
||||
func (m *ApiKeySecurity) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Type != "" {
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
}
|
||||
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})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// 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 != "" {
|
||||
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.
|
||||
func (m *BasicAuthenticationSecurity) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Type != "" {
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
if 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.
|
||||
func (m *BodyParameter) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.Description != "" {
|
||||
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
|
||||
}
|
||||
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: "name", Value: m.Name})
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "in", Value: m.In})
|
||||
if m.Required != false {
|
||||
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
|
||||
}
|
||||
if m.Schema != nil {
|
||||
info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()})
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "schema", Value: m.Schema.ToRawInfo()})
|
||||
// &{Name:schema Type:Schema StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
|
||||
if m.VendorExtension != nil {
|
||||
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.
|
||||
func (m *Contact) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *Default) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *Definitions) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *Document) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Swagger != "" {
|
||||
info = append(info, yaml.MapItem{Key: "swagger", Value: m.Swagger})
|
||||
}
|
||||
if m.Info != nil {
|
||||
info = append(info, yaml.MapItem{Key: "info", Value: m.Info.ToRawInfo()})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// 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:}
|
||||
if 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 {
|
||||
info = append(info, yaml.MapItem{Key: "produces", Value: m.Produces})
|
||||
}
|
||||
if m.Paths != nil {
|
||||
info = append(info, yaml.MapItem{Key: "paths", Value: m.Paths.ToRawInfo()})
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "paths", Value: m.Paths.ToRawInfo()})
|
||||
// &{Name:paths Type:Paths StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
|
||||
if m.Definitions != nil {
|
||||
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.
|
||||
func (m *Examples) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *ExternalDocs) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.Description != "" {
|
||||
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
|
||||
}
|
||||
if m.Url != "" {
|
||||
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "url", Value: m.Url})
|
||||
if m.VendorExtension != nil {
|
||||
for _, item := range m.VendorExtension {
|
||||
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.
|
||||
func (m *FileSchema) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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 {
|
||||
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
|
||||
}
|
||||
if m.Type != "" {
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
if m.ReadOnly != false {
|
||||
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.
|
||||
func (m *FormDataParameterSubSchema) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.Required != false {
|
||||
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.
|
||||
func (m *Header) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Type != "" {
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
if 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.
|
||||
func (m *HeaderParameterSubSchema) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.Required != false {
|
||||
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.
|
||||
func (m *Headers) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *Info) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Title != "" {
|
||||
info = append(info, yaml.MapItem{Key: "title", Value: m.Title})
|
||||
}
|
||||
if m.Version != "" {
|
||||
info = append(info, yaml.MapItem{Key: "version", Value: m.Version})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// 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 != "" {
|
||||
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.
|
||||
func (m *ItemsItem) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if len(m.Schema) != 0 {
|
||||
items := make([]interface{}, 0)
|
||||
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.
|
||||
func (m *JsonReference) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.XRef != "" {
|
||||
info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "$ref", Value: m.XRef})
|
||||
if 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.
|
||||
func (m *License) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Name != "" {
|
||||
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
|
||||
if 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.
|
||||
func (m *NamedAny) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *NamedHeader) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *NamedParameter) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *NamedPathItem) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *NamedResponse) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *NamedResponseValue) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *NamedSchema) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *NamedSecurityDefinitionsItem) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *NamedString) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *NamedStringArray) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *Oauth2AccessCodeSecurity) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Type != "" {
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
}
|
||||
if m.Flow != "" {
|
||||
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// 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 {
|
||||
info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()})
|
||||
}
|
||||
// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
|
||||
if m.AuthorizationUrl != "" {
|
||||
info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl})
|
||||
}
|
||||
if m.TokenUrl != "" {
|
||||
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl})
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
|
||||
if 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.
|
||||
func (m *Oauth2ApplicationSecurity) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Type != "" {
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
}
|
||||
if m.Flow != "" {
|
||||
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// 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 {
|
||||
info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()})
|
||||
}
|
||||
// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
|
||||
if m.TokenUrl != "" {
|
||||
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
|
||||
if 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.
|
||||
func (m *Oauth2ImplicitSecurity) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Type != "" {
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
}
|
||||
if m.Flow != "" {
|
||||
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// 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 {
|
||||
info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()})
|
||||
}
|
||||
// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
|
||||
if m.AuthorizationUrl != "" {
|
||||
info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl})
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "authorizationUrl", Value: m.AuthorizationUrl})
|
||||
if 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.
|
||||
func (m *Oauth2PasswordSecurity) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Type != "" {
|
||||
info = append(info, yaml.MapItem{Key: "type", Value: m.Type})
|
||||
}
|
||||
if m.Flow != "" {
|
||||
info = append(info, yaml.MapItem{Key: "flow", Value: m.Flow})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// 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 {
|
||||
info = append(info, yaml.MapItem{Key: "scopes", Value: m.Scopes.ToRawInfo()})
|
||||
}
|
||||
// &{Name:scopes Type:Oauth2Scopes StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
|
||||
if m.TokenUrl != "" {
|
||||
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "tokenUrl", Value: m.TokenUrl})
|
||||
if 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.
|
||||
func (m *Oauth2Scopes) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// &{Name:additionalProperties Type:NamedString StringEnumValues:[] MapType:string Repeated:true Pattern: Implicit:true Description:}
|
||||
return info
|
||||
}
|
||||
|
|
@ -7945,6 +8014,9 @@ func (m *Oauth2Scopes) ToRawInfo() interface{} {
|
|||
// ToRawInfo returns a description of Operation suitable for JSON or YAML export.
|
||||
func (m *Operation) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if len(m.Tags) != 0 {
|
||||
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})
|
||||
}
|
||||
// &{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 {
|
||||
info = append(info, yaml.MapItem{Key: "responses", Value: m.Responses.ToRawInfo()})
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "responses", Value: m.Responses.ToRawInfo()})
|
||||
// &{Name:responses Type:Responses StringEnumValues:[] MapType: Repeated:false Pattern: Implicit:false Description:}
|
||||
if len(m.Schemes) != 0 {
|
||||
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.
|
||||
func (m *ParameterDefinitions) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *PathItem) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *PathParameterSubSchema) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Required != false {
|
||||
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "required", Value: m.Required})
|
||||
if 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.
|
||||
func (m *Paths) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.VendorExtension != nil {
|
||||
for _, item := range m.VendorExtension {
|
||||
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.
|
||||
func (m *PrimitivesItems) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *Properties) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *QueryParameterSubSchema) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.Required != false {
|
||||
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.
|
||||
func (m *Response) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Description != "" {
|
||||
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "description", Value: m.Description})
|
||||
if m.Schema != nil {
|
||||
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.
|
||||
func (m *ResponseDefinitions) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *Responses) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.ResponseCode != nil {
|
||||
for _, item := range m.ResponseCode {
|
||||
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.
|
||||
func (m *Schema) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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.
|
||||
func (m *SecurityDefinitions) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *SecurityRequirement) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *Tag) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m.Name != "" {
|
||||
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
// always include this required field.
|
||||
info = append(info, yaml.MapItem{Key: "name", Value: m.Name})
|
||||
if 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.
|
||||
func (m *TypeItem) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if len(m.Value) != 0 {
|
||||
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.
|
||||
func (m *VendorExtension) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if m.AdditionalProperties != nil {
|
||||
for _, item := range m.AdditionalProperties {
|
||||
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.
|
||||
func (m *Xml) ToRawInfo() interface{} {
|
||||
info := yaml.MapSlice{}
|
||||
if m == nil {
|
||||
return info
|
||||
}
|
||||
if 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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var fileCache map[string][]byte
|
||||
|
|
@ -31,6 +32,8 @@ var infoCache map[string]interface{}
|
|||
var count int64
|
||||
|
||||
var verboseReader = false
|
||||
var fileCacheEnable = true
|
||||
var infoCacheEnable = true
|
||||
|
||||
func initializeFileCache() {
|
||||
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.
|
||||
func FetchFile(fileurl string) ([]byte, error) {
|
||||
var bytes []byte
|
||||
initializeFileCache()
|
||||
bytes, ok := fileCache[fileurl]
|
||||
if ok {
|
||||
if verboseReader {
|
||||
log.Printf("Cache hit %s", fileurl)
|
||||
if fileCacheEnable {
|
||||
bytes, ok := fileCache[fileurl]
|
||||
if ok {
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode != 200 {
|
||||
return nil, errors.New(fmt.Sprintf("Error downloading %s: %s", fileurl, response.Status))
|
||||
}
|
||||
defer response.Body.Close()
|
||||
bytes, err = ioutil.ReadAll(response.Body)
|
||||
if err == nil {
|
||||
if fileCacheEnable && err == nil {
|
||||
fileCache[fileurl] = bytes
|
||||
}
|
||||
return bytes, err
|
||||
|
|
@ -95,22 +136,24 @@ func ReadBytesForFile(filename string) ([]byte, error) {
|
|||
// ReadInfoFromBytes unmarshals a file as a yaml.MapSlice.
|
||||
func ReadInfoFromBytes(filename string, bytes []byte) (interface{}, error) {
|
||||
initializeInfoCache()
|
||||
cachedInfo, ok := infoCache[filename]
|
||||
if ok {
|
||||
if verboseReader {
|
||||
log.Printf("Cache hit info for file %s", filename)
|
||||
if infoCacheEnable {
|
||||
cachedInfo, ok := infoCache[filename]
|
||||
if ok {
|
||||
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
|
||||
err := yaml.Unmarshal(bytes, &info)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(filename) > 0 {
|
||||
if infoCacheEnable && len(filename) > 0 {
|
||||
infoCache[filename] = info
|
||||
}
|
||||
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.
|
||||
func ReadInfoForRef(basefile string, ref string) (interface{}, error) {
|
||||
initializeInfoCache()
|
||||
{
|
||||
if infoCacheEnable {
|
||||
info, ok := infoCache[ref]
|
||||
if ok {
|
||||
if verboseReader {
|
||||
|
|
@ -127,16 +170,20 @@ func ReadInfoForRef(basefile string, ref string) (interface{}, error) {
|
|||
}
|
||||
return info, nil
|
||||
}
|
||||
}
|
||||
if verboseReader {
|
||||
log.Printf("Reading info for ref %s#%s", basefile, ref)
|
||||
if verboseReader {
|
||||
log.Printf("Reading info for ref %s#%s", basefile, ref)
|
||||
}
|
||||
}
|
||||
count = count + 1
|
||||
basedir, _ := filepath.Split(basefile)
|
||||
parts := strings.Split(ref, "#")
|
||||
var filename string
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
// 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
|
||||
|
||||
import proto "github.com/golang/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
import google_protobuf "github.com/golang/protobuf/ptypes/any"
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
any "github.com/golang/protobuf/ptypes/any"
|
||||
math "math"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
|
|
@ -29,22 +19,45 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// 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.
|
||||
type Version struct {
|
||||
Major int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
|
||||
Minor int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
|
||||
Patch int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
|
||||
Major int32 `protobuf:"varint,1,opt,name=major,proto3" json:"major,omitempty"`
|
||||
Minor int32 `protobuf:"varint,2,opt,name=minor,proto3" json:"minor,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
|
||||
// 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) String() string { return proto.CompactTextString(m) }
|
||||
func (*Version) ProtoMessage() {}
|
||||
func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||
func (m *Version) Reset() { *m = Version{} }
|
||||
func (m *Version) String() string { return proto.CompactTextString(m) }
|
||||
func (*Version) ProtoMessage() {}
|
||||
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 {
|
||||
if m != nil {
|
||||
|
|
@ -78,15 +91,38 @@ func (m *Version) GetSuffix() string {
|
|||
type ExtensionHandlerRequest struct {
|
||||
// The OpenAPI descriptions that were explicitly listed on the command line.
|
||||
// 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.
|
||||
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) String() string { return proto.CompactTextString(m) }
|
||||
func (*ExtensionHandlerRequest) ProtoMessage() {}
|
||||
func (*ExtensionHandlerRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
func (m *ExtensionHandlerRequest) Reset() { *m = ExtensionHandlerRequest{} }
|
||||
func (m *ExtensionHandlerRequest) String() string { return proto.CompactTextString(m) }
|
||||
func (*ExtensionHandlerRequest) ProtoMessage() {}
|
||||
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 {
|
||||
if m != nil {
|
||||
|
|
@ -105,7 +141,7 @@ func (m *ExtensionHandlerRequest) GetCompilerVersion() *Version {
|
|||
// The extensions writes an encoded ExtensionHandlerResponse to stdout.
|
||||
type ExtensionHandlerResponse struct {
|
||||
// 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.
|
||||
// The extension handler process should exit with status code zero
|
||||
// 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
|
||||
// reported by writing a message to stderr and exiting with a non-zero
|
||||
// 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
|
||||
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) String() string { return proto.CompactTextString(m) }
|
||||
func (*ExtensionHandlerResponse) ProtoMessage() {}
|
||||
func (*ExtensionHandlerResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
|
||||
func (m *ExtensionHandlerResponse) Reset() { *m = ExtensionHandlerResponse{} }
|
||||
func (m *ExtensionHandlerResponse) String() string { return proto.CompactTextString(m) }
|
||||
func (*ExtensionHandlerResponse) ProtoMessage() {}
|
||||
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 {
|
||||
if m != nil {
|
||||
|
|
@ -139,7 +198,7 @@ func (m *ExtensionHandlerResponse) GetError() []string {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *ExtensionHandlerResponse) GetValue() *google_protobuf.Any {
|
||||
func (m *ExtensionHandlerResponse) GetValue() *any.Any {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
|
|
@ -148,17 +207,40 @@ func (m *ExtensionHandlerResponse) GetValue() *google_protobuf.Any {
|
|||
|
||||
type Wrapper struct {
|
||||
// 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
|
||||
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
|
||||
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) String() string { return proto.CompactTextString(m) }
|
||||
func (*Wrapper) ProtoMessage() {}
|
||||
func (*Wrapper) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
func (m *Wrapper) Reset() { *m = Wrapper{} }
|
||||
func (m *Wrapper) String() string { return proto.CompactTextString(m) }
|
||||
func (*Wrapper) ProtoMessage() {}
|
||||
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 {
|
||||
if m != nil {
|
||||
|
|
@ -188,31 +270,31 @@ func init() {
|
|||
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{
|
||||
// 357 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x4d, 0x4b, 0xc3, 0x40,
|
||||
0x18, 0x84, 0x49, 0xbf, 0x62, 0x56, 0x6c, 0x65, 0x2d, 0x1a, 0xc5, 0x43, 0x09, 0x08, 0x45, 0x64,
|
||||
0x4b, 0x15, 0xbc, 0xb7, 0x50, 0xd4, 0x8b, 0x2d, 0x7b, 0xa8, 0x37, 0xcb, 0x36, 0x7d, 0x9b, 0x46,
|
||||
0x92, 0xdd, 0x75, 0xf3, 0x61, 0xfb, 0x57, 0x3c, 0xfa, 0x4b, 0x25, 0xbb, 0x49, 0x3d, 0xa8, 0xb7,
|
||||
0xcc, 0xc3, 0x24, 0xef, 0xcc, 0x04, 0x75, 0x60, 0x9b, 0x02, 0x4f, 0x42, 0xc1, 0x89, 0x54, 0x22,
|
||||
0x15, 0xf8, 0x44, 0x48, 0xe0, 0x4c, 0x86, 0x3f, 0x3c, 0x1f, 0x5e, 0x9c, 0x07, 0x42, 0x04, 0x11,
|
||||
0x0c, 0xb4, 0x65, 0x99, 0xad, 0x07, 0x8c, 0xef, 0x8c, 0xdf, 0xf3, 0x91, 0x3d, 0x07, 0x55, 0x18,
|
||||
0x71, 0x17, 0x35, 0x63, 0xf6, 0x26, 0x94, 0x6b, 0xf5, 0xac, 0x7e, 0x93, 0x1a, 0xa1, 0x69, 0xc8,
|
||||
0x85, 0x72, 0x6b, 0x25, 0x2d, 0x44, 0x41, 0x25, 0x4b, 0xfd, 0x8d, 0x5b, 0x37, 0x54, 0x0b, 0x7c,
|
||||
0x8a, 0x5a, 0x49, 0xb6, 0x5e, 0x87, 0x5b, 0xb7, 0xd1, 0xb3, 0xfa, 0x0e, 0x2d, 0x95, 0xf7, 0x69,
|
||||
0xa1, 0xb3, 0x49, 0x15, 0xe8, 0x91, 0xf1, 0x55, 0x04, 0x8a, 0xc2, 0x7b, 0x06, 0x49, 0x8a, 0xef,
|
||||
0x91, 0xfd, 0xa1, 0x98, 0x94, 0x60, 0xee, 0x1e, 0xde, 0x5e, 0x92, 0x3f, 0x2a, 0x90, 0x17, 0xe3,
|
||||
0xa1, 0x95, 0x19, 0x3f, 0xa0, 0x63, 0x5f, 0xc4, 0x32, 0x8c, 0x40, 0x2d, 0x72, 0xd3, 0x40, 0x87,
|
||||
0xf9, 0xef, 0x03, 0x65, 0x4b, 0xda, 0xa9, 0xde, 0x2a, 0x81, 0x97, 0x23, 0xf7, 0x77, 0xb6, 0x44,
|
||||
0x0a, 0x9e, 0x00, 0x76, 0x91, 0xbd, 0xd1, 0x68, 0xa5, 0xc3, 0x1d, 0xd0, 0x4a, 0x16, 0x03, 0x80,
|
||||
0x52, 0x7a, 0x96, 0x7a, 0xdf, 0xa1, 0x46, 0xe0, 0x6b, 0xd4, 0xcc, 0x59, 0x94, 0x41, 0x99, 0xa4,
|
||||
0x4b, 0xcc, 0xf0, 0xa4, 0x1a, 0x9e, 0x8c, 0xf8, 0x8e, 0x1a, 0x8b, 0xf7, 0x8a, 0xec, 0xb2, 0x54,
|
||||
0x71, 0xa6, 0xaa, 0x60, 0xe9, 0xe1, 0x2a, 0x89, 0xaf, 0x50, 0x7b, 0xdf, 0x62, 0xc1, 0x59, 0x0c,
|
||||
0xfa, 0x37, 0x38, 0xf4, 0x68, 0x4f, 0x9f, 0x59, 0x0c, 0x18, 0xa3, 0xc6, 0x8e, 0xc5, 0x91, 0x3e,
|
||||
0xeb, 0x50, 0xfd, 0x3c, 0xbe, 0x41, 0x6d, 0xa1, 0x02, 0x12, 0x70, 0x91, 0xa4, 0xa1, 0x4f, 0xf2,
|
||||
0xe1, 0x18, 0x4f, 0x25, 0xf0, 0xd1, 0xec, 0x69, 0x5f, 0x77, 0x3e, 0x9c, 0x59, 0x5f, 0xb5, 0xfa,
|
||||
0x74, 0x34, 0x59, 0xb6, 0x74, 0xc4, 0xbb, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x84, 0x5c, 0x6b,
|
||||
0x80, 0x51, 0x02, 0x00, 0x00,
|
||||
var fileDescriptor_661e47e790f76671 = []byte{
|
||||
// 362 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x4d, 0x4b, 0xeb, 0x40,
|
||||
0x18, 0x85, 0x49, 0xbf, 0x72, 0x33, 0x97, 0xdb, 0x2b, 0x63, 0xd1, 0x58, 0x5c, 0x94, 0x80, 0x50,
|
||||
0x44, 0xa6, 0x54, 0xc1, 0x7d, 0x0b, 0x45, 0xdd, 0xd8, 0x32, 0x8b, 0xba, 0xb3, 0x4c, 0xd3, 0xb7,
|
||||
0x69, 0x24, 0x99, 0x19, 0x27, 0x1f, 0xb6, 0x7f, 0xc5, 0xa5, 0xbf, 0x54, 0x32, 0x93, 0xc4, 0x85,
|
||||
0xba, 0x9b, 0xf3, 0x70, 0xda, 0xf7, 0x9c, 0x13, 0xd4, 0x87, 0x7d, 0x0a, 0x3c, 0x09, 0x05, 0x4f,
|
||||
0x46, 0xf5, 0x93, 0x48, 0x25, 0x52, 0x81, 0x8f, 0x85, 0x04, 0xce, 0x64, 0xf8, 0xc5, 0xf3, 0x71,
|
||||
0xff, 0x2c, 0x10, 0x22, 0x88, 0x60, 0xa4, 0x2d, 0xeb, 0x6c, 0x3b, 0x62, 0xfc, 0x60, 0xfc, 0x9e,
|
||||
0x8f, 0xec, 0x25, 0xa8, 0xc2, 0x88, 0x7b, 0xa8, 0x1d, 0xb3, 0x17, 0xa1, 0x5c, 0x6b, 0x60, 0x0d,
|
||||
0xdb, 0xd4, 0x08, 0x4d, 0x43, 0x2e, 0x94, 0xdb, 0x28, 0x69, 0x21, 0x0a, 0x2a, 0x59, 0xea, 0xef,
|
||||
0xdc, 0xa6, 0xa1, 0x5a, 0xe0, 0x13, 0xd4, 0x49, 0xb2, 0xed, 0x36, 0xdc, 0xbb, 0xad, 0x81, 0x35,
|
||||
0x74, 0x68, 0xa9, 0xbc, 0x77, 0x0b, 0x9d, 0xce, 0xaa, 0x40, 0xf7, 0x8c, 0x6f, 0x22, 0x50, 0x14,
|
||||
0x5e, 0x33, 0x48, 0x52, 0x7c, 0x8b, 0xec, 0x37, 0xc5, 0xa4, 0x04, 0x73, 0xf7, 0xef, 0xf5, 0x39,
|
||||
0xf9, 0xa1, 0x02, 0x79, 0x32, 0x1e, 0x5a, 0x99, 0xf1, 0x1d, 0x3a, 0xf2, 0x45, 0x2c, 0xc3, 0x08,
|
||||
0xd4, 0x2a, 0x37, 0x0d, 0x74, 0x98, 0xdf, 0xfe, 0xa0, 0x6c, 0x49, 0xff, 0x57, 0xbf, 0x2a, 0x81,
|
||||
0x97, 0x23, 0xf7, 0x7b, 0xb6, 0x44, 0x0a, 0x9e, 0x00, 0x76, 0x91, 0xbd, 0xd3, 0x68, 0xa3, 0xc3,
|
||||
0xfd, 0xa1, 0x95, 0x2c, 0x06, 0x00, 0xa5, 0xf4, 0x2c, 0xcd, 0xa1, 0x43, 0x8d, 0xc0, 0x97, 0xa8,
|
||||
0x9d, 0xb3, 0x28, 0x83, 0x32, 0x49, 0x8f, 0x98, 0xe1, 0x49, 0x35, 0x3c, 0x99, 0xf0, 0x03, 0x35,
|
||||
0x16, 0xef, 0x19, 0xd9, 0x65, 0xa9, 0xe2, 0x4c, 0x55, 0xc1, 0xd2, 0xc3, 0x55, 0x12, 0x5f, 0xa0,
|
||||
0x6e, 0xdd, 0x62, 0xc5, 0x59, 0x0c, 0xfa, 0x33, 0x38, 0xf4, 0x5f, 0x4d, 0x1f, 0x59, 0x0c, 0x18,
|
||||
0xa3, 0xd6, 0x81, 0xc5, 0x91, 0x3e, 0xeb, 0x50, 0xfd, 0x9e, 0x5e, 0xa1, 0xae, 0x50, 0x01, 0x09,
|
||||
0xb8, 0x48, 0xd2, 0xd0, 0x27, 0xf9, 0x78, 0x8a, 0xe7, 0x12, 0xf8, 0x64, 0xf1, 0x50, 0xd7, 0x5d,
|
||||
0x8e, 0x17, 0xd6, 0x47, 0xa3, 0x39, 0x9f, 0xcc, 0xd6, 0x1d, 0x1d, 0xf1, 0xe6, 0x33, 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
|
||||
ADCQ DX,R13
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
SHLQ $13,SI,CX
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ DX,R8
|
||||
ADDQ CX,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ DX,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ DX,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ DX,R14
|
||||
ADDQ R13,R14
|
||||
IMUL3Q $19,R15,CX
|
||||
|
|
@ -236,18 +236,18 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
SHLQ $13,SI,CX
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ DX,R8
|
||||
ADDQ CX,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ DX,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ DX,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ DX,R14
|
||||
ADDQ R13,R14
|
||||
IMUL3Q $19,R15,CX
|
||||
|
|
@ -441,18 +441,18 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
SHLQ $13,SI,CX
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ DX,R8
|
||||
ADDQ CX,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ DX,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ DX,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ DX,R14
|
||||
ADDQ R13,R14
|
||||
IMUL3Q $19,R15,CX
|
||||
|
|
@ -591,18 +591,18 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
SHLQ $13,SI,CX
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ DX,R8
|
||||
ADDQ CX,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ DX,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ DX,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ DX,R14
|
||||
ADDQ R13,R14
|
||||
IMUL3Q $19,R15,CX
|
||||
|
|
@ -731,18 +731,18 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
SHLQ $13,SI,CX
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ DX,R8
|
||||
ADDQ CX,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ DX,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ DX,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ DX,R14
|
||||
ADDQ R13,R14
|
||||
IMUL3Q $19,R15,CX
|
||||
|
|
@ -846,18 +846,18 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
SHLQ $13,SI,CX
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ DX,R8
|
||||
ADDQ CX,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ DX,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ DX,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ DX,R14
|
||||
ADDQ R13,R14
|
||||
IMUL3Q $19,R15,CX
|
||||
|
|
@ -996,18 +996,18 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
SHLQ $13,SI,CX
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ DX,R8
|
||||
ADDQ CX,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ DX,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ DX,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ DX,R14
|
||||
ADDQ R13,R14
|
||||
IMUL3Q $19,R15,CX
|
||||
|
|
@ -1146,18 +1146,18 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
SHLQ $13,SI,CX
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ DX,R8
|
||||
ADDQ CX,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ DX,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ DX,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ DX,R14
|
||||
ADDQ R13,R14
|
||||
IMUL3Q $19,R15,CX
|
||||
|
|
@ -1332,18 +1332,18 @@ TEXT ·ladderstep(SB),0,$296-8
|
|||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
SHLQ $13,SI,CX
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ DX,R8
|
||||
ADDQ CX,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ DX,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ DX,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ DX,R14
|
||||
ADDQ R13,R14
|
||||
IMUL3Q $19,R15,CX
|
||||
|
|
|
|||
|
|
@ -124,18 +124,18 @@ TEXT ·mul(SB),0,$16-24
|
|||
ADDQ AX,R14
|
||||
ADCQ DX,R15
|
||||
MOVQ $REDMASK51,SI
|
||||
SHLQ $13,R9:R8
|
||||
SHLQ $13,R8,R9
|
||||
ANDQ SI,R8
|
||||
SHLQ $13,R11:R10
|
||||
SHLQ $13,R10,R11
|
||||
ANDQ SI,R10
|
||||
ADDQ R9,R10
|
||||
SHLQ $13,R13:R12
|
||||
SHLQ $13,R12,R13
|
||||
ANDQ SI,R12
|
||||
ADDQ R11,R12
|
||||
SHLQ $13,R15:R14
|
||||
SHLQ $13,R14,R15
|
||||
ANDQ SI,R14
|
||||
ADDQ R13,R14
|
||||
SHLQ $13,BP:BX
|
||||
SHLQ $13,BX,BP
|
||||
ANDQ SI,BX
|
||||
ADDQ R15,BX
|
||||
IMUL3Q $19,BP,DX
|
||||
|
|
|
|||
|
|
@ -87,18 +87,18 @@ TEXT ·square(SB),7,$0-16
|
|||
ADDQ AX,R13
|
||||
ADCQ DX,R14
|
||||
MOVQ $REDMASK51,SI
|
||||
SHLQ $13,R8:CX
|
||||
SHLQ $13,CX,R8
|
||||
ANDQ SI,CX
|
||||
SHLQ $13,R10:R9
|
||||
SHLQ $13,R9,R10
|
||||
ANDQ SI,R9
|
||||
ADDQ R8,R9
|
||||
SHLQ $13,R12:R11
|
||||
SHLQ $13,R11,R12
|
||||
ANDQ SI,R11
|
||||
ADDQ R10,R11
|
||||
SHLQ $13,R14:R13
|
||||
SHLQ $13,R13,R14
|
||||
ANDQ SI,R13
|
||||
ADDQ R12,R13
|
||||
SHLQ $13,BX:R15
|
||||
SHLQ $13,R15,BX
|
||||
ANDQ SI,R15
|
||||
ADDQ R14,R15
|
||||
IMUL3Q $19,BX,DX
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ go_library(
|
|||
name = "go_default_library",
|
||||
srcs = [
|
||||
"hsalsa20.go",
|
||||
"salsa2020_amd64.s",
|
||||
"salsa208.go",
|
||||
"salsa20_amd64.go",
|
||||
"salsa20_amd64.s",
|
||||
"salsa20_noasm.go",
|
||||
"salsa20_ref.go",
|
||||
],
|
||||
importmap = "k8s.io/kops/vendor/golang.org/x/crypto/salsa20/salsa",
|
||||
|
|
|
|||
|
|
@ -6,10 +6,9 @@
|
|||
|
||||
package salsa
|
||||
|
||||
// This function is implemented in salsa2020_amd64.s.
|
||||
|
||||
//go:noescape
|
||||
|
||||
// salsa2020XORKeyStream is implemented in salsa20_amd64.s.
|
||||
func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte)
|
||||
|
||||
// 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 DX,288(SP)
|
||||
MOVL CX,304(SP)
|
||||
ADDQ $1,DX
|
||||
SHLQ $32,CX
|
||||
ADDQ CX,DX
|
||||
ADDQ $1,DX
|
||||
MOVQ DX,CX
|
||||
SHRQ $32,CX
|
||||
MOVL DX, 292 (SP)
|
||||
MOVL CX, 308 (SP)
|
||||
ADDQ $1,DX
|
||||
SHLQ $32,CX
|
||||
ADDQ CX,DX
|
||||
MOVQ DX,CX
|
||||
SHRQ $32,CX
|
||||
MOVL DX, 296 (SP)
|
||||
MOVL CX, 312 (SP)
|
||||
ADDQ $1,DX
|
||||
SHLQ $32,CX
|
||||
ADDQ CX,DX
|
||||
MOVQ DX,CX
|
||||
SHRQ $32,CX
|
||||
MOVL DX, 300 (SP)
|
||||
MOVL CX, 316 (SP)
|
||||
ADDQ $1,DX
|
||||
SHLQ $32,CX
|
||||
ADDQ CX,DX
|
||||
MOVQ DX,CX
|
||||
SHRQ $32,CX
|
||||
MOVL DX,16(SP)
|
||||
|
|
@ -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
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !amd64 appengine gccgo
|
||||
|
||||
package salsa
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// 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 is the generic implementation of XORKeyStream to be used
|
||||
// when no assembly implementation is available.
|
||||
func genericXORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) {
|
||||
var block [64]byte
|
||||
var counterCopy [16]byte
|
||||
copy(counterCopy[:], counter[:])
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ package scrypt // import "golang.org/x/crypto/scrypt"
|
|||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"math/bits"
|
||||
|
||||
"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
|
||||
|
||||
for i := 0; i < 8; i += 2 {
|
||||
u := x0 + x12
|
||||
x4 ^= u<<7 | u>>(32-7)
|
||||
u = x4 + x0
|
||||
x8 ^= u<<9 | u>>(32-9)
|
||||
u = x8 + x4
|
||||
x12 ^= u<<13 | u>>(32-13)
|
||||
u = x12 + x8
|
||||
x0 ^= u<<18 | u>>(32-18)
|
||||
x4 ^= bits.RotateLeft32(x0+x12, 7)
|
||||
x8 ^= bits.RotateLeft32(x4+x0, 9)
|
||||
x12 ^= bits.RotateLeft32(x8+x4, 13)
|
||||
x0 ^= bits.RotateLeft32(x12+x8, 18)
|
||||
|
||||
u = x5 + x1
|
||||
x9 ^= u<<7 | u>>(32-7)
|
||||
u = x9 + x5
|
||||
x13 ^= u<<9 | u>>(32-9)
|
||||
u = x13 + x9
|
||||
x1 ^= u<<13 | u>>(32-13)
|
||||
u = x1 + x13
|
||||
x5 ^= u<<18 | u>>(32-18)
|
||||
x9 ^= bits.RotateLeft32(x5+x1, 7)
|
||||
x13 ^= bits.RotateLeft32(x9+x5, 9)
|
||||
x1 ^= bits.RotateLeft32(x13+x9, 13)
|
||||
x5 ^= bits.RotateLeft32(x1+x13, 18)
|
||||
|
||||
u = x10 + x6
|
||||
x14 ^= u<<7 | u>>(32-7)
|
||||
u = x14 + x10
|
||||
x2 ^= u<<9 | u>>(32-9)
|
||||
u = x2 + x14
|
||||
x6 ^= u<<13 | u>>(32-13)
|
||||
u = x6 + x2
|
||||
x10 ^= u<<18 | u>>(32-18)
|
||||
x14 ^= bits.RotateLeft32(x10+x6, 7)
|
||||
x2 ^= bits.RotateLeft32(x14+x10, 9)
|
||||
x6 ^= bits.RotateLeft32(x2+x14, 13)
|
||||
x10 ^= bits.RotateLeft32(x6+x2, 18)
|
||||
|
||||
u = x15 + x11
|
||||
x3 ^= u<<7 | u>>(32-7)
|
||||
u = x3 + x15
|
||||
x7 ^= u<<9 | u>>(32-9)
|
||||
u = x7 + x3
|
||||
x11 ^= u<<13 | u>>(32-13)
|
||||
u = x11 + x7
|
||||
x15 ^= u<<18 | u>>(32-18)
|
||||
x3 ^= bits.RotateLeft32(x15+x11, 7)
|
||||
x7 ^= bits.RotateLeft32(x3+x15, 9)
|
||||
x11 ^= bits.RotateLeft32(x7+x3, 13)
|
||||
x15 ^= bits.RotateLeft32(x11+x7, 18)
|
||||
|
||||
u = x0 + x3
|
||||
x1 ^= u<<7 | u>>(32-7)
|
||||
u = x1 + x0
|
||||
x2 ^= u<<9 | u>>(32-9)
|
||||
u = x2 + x1
|
||||
x3 ^= u<<13 | u>>(32-13)
|
||||
u = x3 + x2
|
||||
x0 ^= u<<18 | u>>(32-18)
|
||||
x1 ^= bits.RotateLeft32(x0+x3, 7)
|
||||
x2 ^= bits.RotateLeft32(x1+x0, 9)
|
||||
x3 ^= bits.RotateLeft32(x2+x1, 13)
|
||||
x0 ^= bits.RotateLeft32(x3+x2, 18)
|
||||
|
||||
u = x5 + x4
|
||||
x6 ^= u<<7 | u>>(32-7)
|
||||
u = x6 + x5
|
||||
x7 ^= u<<9 | u>>(32-9)
|
||||
u = x7 + x6
|
||||
x4 ^= u<<13 | u>>(32-13)
|
||||
u = x4 + x7
|
||||
x5 ^= u<<18 | u>>(32-18)
|
||||
x6 ^= bits.RotateLeft32(x5+x4, 7)
|
||||
x7 ^= bits.RotateLeft32(x6+x5, 9)
|
||||
x4 ^= bits.RotateLeft32(x7+x6, 13)
|
||||
x5 ^= bits.RotateLeft32(x4+x7, 18)
|
||||
|
||||
u = x10 + x9
|
||||
x11 ^= u<<7 | u>>(32-7)
|
||||
u = x11 + x10
|
||||
x8 ^= u<<9 | u>>(32-9)
|
||||
u = x8 + x11
|
||||
x9 ^= u<<13 | u>>(32-13)
|
||||
u = x9 + x8
|
||||
x10 ^= u<<18 | u>>(32-18)
|
||||
x11 ^= bits.RotateLeft32(x10+x9, 7)
|
||||
x8 ^= bits.RotateLeft32(x11+x10, 9)
|
||||
x9 ^= bits.RotateLeft32(x8+x11, 13)
|
||||
x10 ^= bits.RotateLeft32(x9+x8, 18)
|
||||
|
||||
u = x15 + x14
|
||||
x12 ^= u<<7 | u>>(32-7)
|
||||
u = x12 + x15
|
||||
x13 ^= u<<9 | u>>(32-9)
|
||||
u = x13 + x12
|
||||
x14 ^= u<<13 | u>>(32-13)
|
||||
u = x14 + x13
|
||||
x15 ^= u<<18 | u>>(32-18)
|
||||
x12 ^= bits.RotateLeft32(x15+x14, 7)
|
||||
x13 ^= bits.RotateLeft32(x12+x15, 9)
|
||||
x14 ^= bits.RotateLeft32(x13+x12, 13)
|
||||
x15 ^= bits.RotateLeft32(x14+x13, 18)
|
||||
}
|
||||
x0 += w0
|
||||
x1 += w1
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ go_library(
|
|||
"mux.go",
|
||||
"server.go",
|
||||
"session.go",
|
||||
"ssh_gss.go",
|
||||
"streamlocal.go",
|
||||
"tcpip.go",
|
||||
"transport.go",
|
||||
|
|
|
|||
|
|
@ -149,8 +149,8 @@ type streamPacketCipher struct {
|
|||
macResult []byte
|
||||
}
|
||||
|
||||
// readPacket reads and decrypt a single packet from the reader argument.
|
||||
func (s *streamPacketCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
|
||||
// readCipherPacket reads and decrypt a single packet from the reader argument.
|
||||
func (s *streamPacketCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
|
||||
if _, err := io.ReadFull(r, s.prefix[:]); err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
// writePacket encrypts and sends a packet of data to the writer argument
|
||||
func (s *streamPacketCipher) writePacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
|
||||
// writeCipherPacket encrypts and sends a packet of data to the writer argument
|
||||
func (s *streamPacketCipher) writeCipherPacket(seqNum uint32, w io.Writer, rand io.Reader, packet []byte) error {
|
||||
if len(packet) > maxPacket {
|
||||
return errors.New("ssh: packet too large")
|
||||
}
|
||||
|
|
@ -327,7 +327,7 @@ func newGCMCipher(key, iv, unusedMacKey []byte, unusedAlgs directionAlgorithms)
|
|||
|
||||
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
|
||||
// stream cipher because that encrypts the length too.
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -486,8 +486,8 @@ type cbcError string
|
|||
|
||||
func (e cbcError) Error() string { return string(e) }
|
||||
|
||||
func (c *cbcCipher) readPacket(seqNum uint32, r io.Reader) ([]byte, error) {
|
||||
p, err := c.readPacketLeaky(seqNum, r)
|
||||
func (c *cbcCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) {
|
||||
p, err := c.readCipherPacketLeaky(seqNum, r)
|
||||
if err != nil {
|
||||
if _, ok := err.(cbcError); ok {
|
||||
// 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
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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())
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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)}
|
||||
s := chacha20.New(c.contentKey, nonce)
|
||||
var polyKey [32]byte
|
||||
|
|
@ -723,7 +723,7 @@ func (c *chacha20Poly1305Cipher) readPacket(seqNum uint32, r io.Reader) ([]byte,
|
|||
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)}
|
||||
s := chacha20.New(c.contentKey, nonce)
|
||||
var polyKey [32]byte
|
||||
|
|
|
|||
|
|
@ -523,3 +523,117 @@ func (r *retryableAuthMethod) method() string {
|
|||
func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod {
|
||||
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)
|
||||
}
|
||||
|
||||
// directionAlgorithms records algorithm choices in one direction (either read or write)
|
||||
type directionAlgorithms struct {
|
||||
Cipher string
|
||||
MAC string
|
||||
|
|
@ -137,7 +138,7 @@ type algorithms struct {
|
|||
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.kex, err = findCommon("key exchange", clientKexInit.KexAlgos, serverKexInit.KexAlgos)
|
||||
|
|
@ -150,32 +151,37 @@ func findAgreedAlgorithms(clientKexInit, serverKexInit *kexInitMsg) (algs *algor
|
|||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -543,7 +543,8 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
|||
|
||||
clientInit := otherInit
|
||||
serverInit := t.sentInitMsg
|
||||
if len(t.hostKeys) == 0 {
|
||||
isClient := len(t.hostKeys) == 0
|
||||
if isClient {
|
||||
clientInit, serverInit = serverInit, clientInit
|
||||
|
||||
magics.clientKexInit = t.sentInitPacket
|
||||
|
|
@ -551,7 +552,7 @@ func (t *handshakeTransport) enterKeyExchange(otherInitPacket []byte) error {
|
|||
}
|
||||
|
||||
var err error
|
||||
t.algorithms, err = findAgreedAlgorithms(clientInit, serverInit)
|
||||
t.algorithms, err = findAgreedAlgorithms(isClient, clientInit, serverInit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,6 +275,42 @@ type userAuthPubKeyOkMsg struct {
|
|||
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
|
||||
// should be a struct. The possible values are separated by a '|' character.
|
||||
func typeTags(structType reflect.Type) (tags []byte) {
|
||||
|
|
@ -756,6 +792,14 @@ func decode(packet []byte) (interface{}, error) {
|
|||
msg = new(channelRequestSuccessMsg)
|
||||
case msgChannelFailure:
|
||||
msg = new(channelRequestFailureMsg)
|
||||
case msgUserAuthGSSAPIToken:
|
||||
msg = new(userAuthGSSAPIToken)
|
||||
case msgUserAuthGSSAPIMIC:
|
||||
msg = new(userAuthGSSAPIMIC)
|
||||
case msgUserAuthGSSAPIErrTok:
|
||||
msg = new(userAuthGSSAPIErrTok)
|
||||
case msgUserAuthGSSAPIError:
|
||||
msg = new(userAuthGSSAPIError)
|
||||
default:
|
||||
return nil, unexpectedMessageError(0, packet[0])
|
||||
}
|
||||
|
|
@ -764,3 +808,29 @@ func decode(packet []byte) (interface{}, error) {
|
|||
}
|
||||
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
|
||||
}
|
||||
|
||||
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.
|
||||
type ServerConfig struct {
|
||||
// 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
|
||||
// the client after key exchange completed but before authentication.
|
||||
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
|
||||
|
|
@ -204,7 +222,9 @@ func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error)
|
|||
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")
|
||||
}
|
||||
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
||||
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
|
||||
// sometimes returned by NewServerConn. It appends any authentication
|
||||
// errors that may occur, and is returned if all of the authentication
|
||||
|
|
@ -496,6 +565,49 @@ userAuthLoop:
|
|||
authErr = candidate.result
|
||||
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:
|
||||
authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
|
||||
}
|
||||
|
|
@ -522,6 +634,10 @@ userAuthLoop:
|
|||
if config.KeyboardInteractiveCallback != nil {
|
||||
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 {
|
||||
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 (
|
||||
"bytes"
|
||||
"io"
|
||||
"strconv"
|
||||
"sync"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
|
@ -271,34 +272,44 @@ func (t *Terminal) moveCursorToPos(pos int) {
|
|||
}
|
||||
|
||||
func (t *Terminal) move(up, down, left, right int) {
|
||||
movement := make([]rune, 3*(up+down+left+right))
|
||||
m := movement
|
||||
for i := 0; i < up; i++ {
|
||||
m[0] = keyEscape
|
||||
m[1] = '['
|
||||
m[2] = 'A'
|
||||
m = m[3:]
|
||||
}
|
||||
for i := 0; i < down; i++ {
|
||||
m[0] = keyEscape
|
||||
m[1] = '['
|
||||
m[2] = 'B'
|
||||
m = m[3:]
|
||||
}
|
||||
for i := 0; i < left; i++ {
|
||||
m[0] = keyEscape
|
||||
m[1] = '['
|
||||
m[2] = 'D'
|
||||
m = m[3:]
|
||||
}
|
||||
for i := 0; i < right; i++ {
|
||||
m[0] = keyEscape
|
||||
m[1] = '['
|
||||
m[2] = 'C'
|
||||
m = m[3:]
|
||||
m := []rune{}
|
||||
|
||||
// 1 unit up can be expressed as ^[[A or ^[A
|
||||
// 5 units up can be expressed as ^[[5A
|
||||
|
||||
if up == 1 {
|
||||
m = append(m, keyEscape, '[', 'A')
|
||||
} else if up > 1 {
|
||||
m = append(m, keyEscape, '[')
|
||||
m = append(m, []rune(strconv.Itoa(up))...)
|
||||
m = append(m, 'A')
|
||||
}
|
||||
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -53,14 +53,14 @@ type transport struct {
|
|||
// packetCipher represents a combination of SSH encryption/MAC
|
||||
// protocol. A single instance should be used for one direction only.
|
||||
type packetCipher interface {
|
||||
// writePacket encrypts the packet and writes it to w. The
|
||||
// writeCipherPacket encrypts the packet and writes it to w. The
|
||||
// contents of the packet are generally scrambled.
|
||||
writePacket(seqnum uint32, w io.Writer, rand io.Reader, packet []byte) error
|
||||
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
|
||||
// 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
|
||||
|
|
@ -127,7 +127,7 @@ func (t *transport) readPacket() (p []byte, err 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++
|
||||
if err == nil && len(packet) == 0 {
|
||||
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 {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,6 +153,11 @@ func main() {
|
|||
}
|
||||
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.
|
||||
in := parseParamList(inps)
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
func Pipe(p []int) (err error) {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,23 @@ func nametomib(name string) (mib []_C_int, err error) {
|
|||
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) {
|
||||
mib, err := sysctlmib(name)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -294,6 +294,13 @@ func GetsockoptTimeval(fd, level, opt int) (*Timeval, error) {
|
|||
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) {
|
||||
var rsa RawSockaddrAny
|
||||
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) {
|
||||
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) {
|
||||
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) {
|
||||
if domain == AF_INET6 && SocketDisableIPv6 {
|
||||
return -1, EAFNOSUPPORT
|
||||
|
|
|
|||
|
|
@ -275,3 +275,9 @@ const (
|
|||
// uname
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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 (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -652,6 +694,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x8
|
||||
|
|
|
|||
|
|
@ -444,139 +444,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -653,6 +695,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x10
|
||||
|
|
|
|||
|
|
@ -447,139 +447,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -656,6 +698,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x8
|
||||
|
|
|
|||
|
|
@ -445,139 +445,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -654,6 +696,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x10
|
||||
|
|
|
|||
|
|
@ -446,139 +446,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -655,6 +697,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x8
|
||||
|
|
|
|||
|
|
@ -445,139 +445,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -654,6 +696,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x10
|
||||
|
|
|
|||
|
|
@ -445,139 +445,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -654,6 +696,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x10
|
||||
|
|
|
|||
|
|
@ -446,139 +446,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -655,6 +697,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x8
|
||||
|
|
|
|||
|
|
@ -446,139 +446,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -655,6 +697,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x10
|
||||
|
|
|
|||
|
|
@ -446,139 +446,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -655,6 +697,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x10
|
||||
|
|
|
|||
|
|
@ -445,139 +445,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -654,6 +696,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x10
|
||||
|
|
|
|||
|
|
@ -444,139 +444,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -653,6 +695,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x10
|
||||
|
|
|
|||
|
|
@ -448,139 +448,181 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_MAX = 0x33
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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
|
||||
NDA_UNSPEC = 0x0
|
||||
NDA_DST = 0x1
|
||||
NDA_LLADDR = 0x2
|
||||
NDA_CACHEINFO = 0x3
|
||||
NDA_PROBES = 0x4
|
||||
NDA_VLAN = 0x5
|
||||
NDA_PORT = 0x6
|
||||
NDA_VNI = 0x7
|
||||
NDA_IFINDEX = 0x8
|
||||
NDA_MASTER = 0x9
|
||||
NDA_LINK_NETNSID = 0xa
|
||||
NDA_SRC_VNI = 0xb
|
||||
NTF_USE = 0x1
|
||||
NTF_SELF = 0x2
|
||||
NTF_MASTER = 0x4
|
||||
NTF_PROXY = 0x8
|
||||
NTF_EXT_LEARNED = 0x10
|
||||
NTF_OFFLOADED = 0x20
|
||||
NTF_ROUTER = 0x80
|
||||
NUD_INCOMPLETE = 0x1
|
||||
NUD_REACHABLE = 0x2
|
||||
NUD_STALE = 0x4
|
||||
NUD_DELAY = 0x8
|
||||
NUD_PROBE = 0x10
|
||||
NUD_FAILED = 0x20
|
||||
NUD_NOARP = 0x40
|
||||
NUD_PERMANENT = 0x80
|
||||
NUD_NONE = 0x0
|
||||
IFA_UNSPEC = 0x0
|
||||
IFA_ADDRESS = 0x1
|
||||
IFA_LOCAL = 0x2
|
||||
IFA_LABEL = 0x3
|
||||
IFA_BROADCAST = 0x4
|
||||
IFA_ANYCAST = 0x5
|
||||
IFA_CACHEINFO = 0x6
|
||||
IFA_MULTICAST = 0x7
|
||||
IFA_FLAGS = 0x8
|
||||
IFA_RT_PRIORITY = 0x9
|
||||
IFA_TARGET_NETNSID = 0xa
|
||||
IFLA_UNSPEC = 0x0
|
||||
IFLA_ADDRESS = 0x1
|
||||
IFLA_BROADCAST = 0x2
|
||||
IFLA_IFNAME = 0x3
|
||||
IFLA_MTU = 0x4
|
||||
IFLA_LINK = 0x5
|
||||
IFLA_QDISC = 0x6
|
||||
IFLA_STATS = 0x7
|
||||
IFLA_COST = 0x8
|
||||
IFLA_PRIORITY = 0x9
|
||||
IFLA_MASTER = 0xa
|
||||
IFLA_WIRELESS = 0xb
|
||||
IFLA_PROTINFO = 0xc
|
||||
IFLA_TXQLEN = 0xd
|
||||
IFLA_MAP = 0xe
|
||||
IFLA_WEIGHT = 0xf
|
||||
IFLA_OPERSTATE = 0x10
|
||||
IFLA_LINKMODE = 0x11
|
||||
IFLA_LINKINFO = 0x12
|
||||
IFLA_NET_NS_PID = 0x13
|
||||
IFLA_IFALIAS = 0x14
|
||||
IFLA_NUM_VF = 0x15
|
||||
IFLA_VFINFO_LIST = 0x16
|
||||
IFLA_STATS64 = 0x17
|
||||
IFLA_VF_PORTS = 0x18
|
||||
IFLA_PORT_SELF = 0x19
|
||||
IFLA_AF_SPEC = 0x1a
|
||||
IFLA_GROUP = 0x1b
|
||||
IFLA_NET_NS_FD = 0x1c
|
||||
IFLA_EXT_MASK = 0x1d
|
||||
IFLA_PROMISCUITY = 0x1e
|
||||
IFLA_NUM_TX_QUEUES = 0x1f
|
||||
IFLA_NUM_RX_QUEUES = 0x20
|
||||
IFLA_CARRIER = 0x21
|
||||
IFLA_PHYS_PORT_ID = 0x22
|
||||
IFLA_CARRIER_CHANGES = 0x23
|
||||
IFLA_PHYS_SWITCH_ID = 0x24
|
||||
IFLA_LINK_NETNSID = 0x25
|
||||
IFLA_PHYS_PORT_NAME = 0x26
|
||||
IFLA_PROTO_DOWN = 0x27
|
||||
IFLA_GSO_MAX_SEGS = 0x28
|
||||
IFLA_GSO_MAX_SIZE = 0x29
|
||||
IFLA_PAD = 0x2a
|
||||
IFLA_XDP = 0x2b
|
||||
IFLA_EVENT = 0x2c
|
||||
IFLA_NEW_NETNSID = 0x2d
|
||||
IFLA_IF_NETNSID = 0x2e
|
||||
IFLA_TARGET_NETNSID = 0x2e
|
||||
IFLA_CARRIER_UP_COUNT = 0x2f
|
||||
IFLA_CARRIER_DOWN_COUNT = 0x30
|
||||
IFLA_NEW_IFINDEX = 0x31
|
||||
IFLA_MIN_MTU = 0x32
|
||||
IFLA_MAX_MTU = 0x33
|
||||
IFLA_MAX = 0x33
|
||||
IFLA_INFO_KIND = 0x1
|
||||
IFLA_INFO_DATA = 0x2
|
||||
IFLA_INFO_XSTATS = 0x3
|
||||
IFLA_INFO_SLAVE_KIND = 0x4
|
||||
IFLA_INFO_SLAVE_DATA = 0x5
|
||||
RT_SCOPE_UNIVERSE = 0x0
|
||||
RT_SCOPE_SITE = 0xc8
|
||||
RT_SCOPE_LINK = 0xfd
|
||||
RT_SCOPE_HOST = 0xfe
|
||||
RT_SCOPE_NOWHERE = 0xff
|
||||
RT_TABLE_UNSPEC = 0x0
|
||||
RT_TABLE_COMPAT = 0xfc
|
||||
RT_TABLE_DEFAULT = 0xfd
|
||||
RT_TABLE_MAIN = 0xfe
|
||||
RT_TABLE_LOCAL = 0xff
|
||||
RT_TABLE_MAX = 0xffffffff
|
||||
RTA_UNSPEC = 0x0
|
||||
RTA_DST = 0x1
|
||||
RTA_SRC = 0x2
|
||||
RTA_IIF = 0x3
|
||||
RTA_OIF = 0x4
|
||||
RTA_GATEWAY = 0x5
|
||||
RTA_PRIORITY = 0x6
|
||||
RTA_PREFSRC = 0x7
|
||||
RTA_METRICS = 0x8
|
||||
RTA_MULTIPATH = 0x9
|
||||
RTA_FLOW = 0xb
|
||||
RTA_CACHEINFO = 0xc
|
||||
RTA_TABLE = 0xf
|
||||
RTA_MARK = 0x10
|
||||
RTA_MFC_STATS = 0x11
|
||||
RTA_VIA = 0x12
|
||||
RTA_NEWDST = 0x13
|
||||
RTA_PREF = 0x14
|
||||
RTA_ENCAP_TYPE = 0x15
|
||||
RTA_ENCAP = 0x16
|
||||
RTA_EXPIRES = 0x17
|
||||
RTA_PAD = 0x18
|
||||
RTA_UID = 0x19
|
||||
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 {
|
||||
|
|
@ -657,6 +699,16 @@ type NdUseroptmsg struct {
|
|||
Pad3 uint32
|
||||
}
|
||||
|
||||
type NdMsg struct {
|
||||
Family uint8
|
||||
Pad1 uint8
|
||||
Pad2 uint16
|
||||
Ifindex int32
|
||||
State uint16
|
||||
Flags uint8
|
||||
Type uint8
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockFilter = 0x8
|
||||
SizeofSockFprog = 0x10
|
||||
|
|
|
|||
|
|
@ -558,3 +558,13 @@ type Uvmexp struct {
|
|||
Fpswtch 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
|
||||
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
|
||||
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",
|
||||
"exec_windows.go",
|
||||
"memory_windows.go",
|
||||
"mkerrors.go",
|
||||
"mksyscall.go",
|
||||
"race.go",
|
||||
"race0.go",
|
||||
|
|
@ -22,6 +23,7 @@ go_library(
|
|||
"types_windows.go",
|
||||
"types_windows_386.go",
|
||||
"types_windows_amd64.go",
|
||||
"zerrors_windows.go",
|
||||
"zsyscall_windows.go",
|
||||
],
|
||||
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 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 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 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 (
|
||||
// do not reorder
|
||||
TOKEN_ASSIGN_PRIMARY = 1 << iota
|
||||
|
|
|
|||
|
|
@ -99,8 +99,6 @@ const (
|
|||
SERVICE_CONFIG_DESCRIPTION = 1
|
||||
SERVICE_CONFIG_FAILURE_ACTIONS = 2
|
||||
|
||||
NO_ERROR = 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 ReadFile(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 CloseHandle(handle Handle) (err error)
|
||||
//sys GetStdHandle(stdhandle uint32) (handle Handle, err error) [failretval==InvalidHandle]
|
||||
|
|
|
|||
|
|
@ -6,33 +6,6 @@ package windows
|
|||
|
||||
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 (
|
||||
// Invented values to support what package os expects.
|
||||
O_RDONLY = 0x00000
|
||||
|
|
@ -126,9 +99,19 @@ const (
|
|||
OPEN_ALWAYS = 4
|
||||
TRUNCATE_EXISTING = 5
|
||||
|
||||
FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
|
||||
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
|
||||
FILE_FLAG_OVERLAPPED = 0x40000000
|
||||
FILE_FLAG_OPEN_REQUIRING_OPLOCK = 0x00040000
|
||||
FILE_FLAG_FIRST_PIPE_INSTANCE = 0x00080000
|
||||
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
|
||||
STARTF_USESTDHANDLES = 0x00000100
|
||||
|
|
@ -167,7 +150,6 @@ const (
|
|||
IGNORE = 0
|
||||
INFINITE = 0xffffffff
|
||||
|
||||
WAIT_TIMEOUT = 258
|
||||
WAIT_ABANDONED = 0x00000080
|
||||
WAIT_OBJECT_0 = 0x00000000
|
||||
WAIT_FAILED = 0xFFFFFFFF
|
||||
|
|
@ -402,12 +384,6 @@ const (
|
|||
CERT_CHAIN_POLICY_EV = 8
|
||||
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_CLIENT = 1
|
||||
AUTHTYPE_SERVER = 2
|
||||
|
|
@ -849,10 +825,6 @@ const (
|
|||
DNS_TYPE_NBSTAT = 0xff01
|
||||
)
|
||||
|
||||
const (
|
||||
DNS_INFO_NO_RECORDS = 0x251D
|
||||
)
|
||||
|
||||
const (
|
||||
// flags inside DNSRecord.Dw
|
||||
DnsSectionQuestion = 0x0000
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -77,6 +77,7 @@ var (
|
|||
procCreateFileW = modkernel32.NewProc("CreateFileW")
|
||||
procReadFile = modkernel32.NewProc("ReadFile")
|
||||
procWriteFile = modkernel32.NewProc("WriteFile")
|
||||
procGetOverlappedResult = modkernel32.NewProc("GetOverlappedResult")
|
||||
procSetFilePointer = modkernel32.NewProc("SetFilePointer")
|
||||
procCloseHandle = modkernel32.NewProc("CloseHandle")
|
||||
procGetStdHandle = modkernel32.NewProc("GetStdHandle")
|
||||
|
|
@ -246,6 +247,7 @@ var (
|
|||
procGetLengthSid = modadvapi32.NewProc("GetLengthSid")
|
||||
procCopySid = modadvapi32.NewProc("CopySid")
|
||||
procAllocateAndInitializeSid = modadvapi32.NewProc("AllocateAndInitializeSid")
|
||||
procCreateWellKnownSid = modadvapi32.NewProc("CreateWellKnownSid")
|
||||
procFreeSid = modadvapi32.NewProc("FreeSid")
|
||||
procEqualSid = modadvapi32.NewProc("EqualSid")
|
||||
procCheckTokenMembership = modadvapi32.NewProc("CheckTokenMembership")
|
||||
|
|
@ -653,6 +655,24 @@ func WriteFile(handle Handle, buf []byte, done *uint32, overlapped *Overlapped)
|
|||
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) {
|
||||
r0, _, e1 := syscall.Syscall6(procSetFilePointer.Addr(), 4, uintptr(handle), uintptr(lowoffset), uintptr(unsafe.Pointer(highoffsetptr)), uintptr(whence), 0, 0)
|
||||
newlowoffset = uint32(r0)
|
||||
|
|
@ -2654,6 +2674,18 @@ func AllocateAndInitializeSid(identAuth *SidIdentifierAuthority, subAuth byte, s
|
|||
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) {
|
||||
r1, _, e1 := syscall.Syscall(procFreeSid.Addr(), 1, uintptr(unsafe.Pointer(sid)), 0, 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