From d141ec869b27b4f3431ce77a791fcf72448e787d Mon Sep 17 00:00:00 2001 From: naison <895703375@qq.com> Date: Wed, 9 Oct 2024 19:17:50 +0800 Subject: [PATCH] fix: fix dns on linux (#336) * fix: fix dns on linux * feat: detect run in Github action or not to setup DNS --- go.mod | 64 +- go.sum | 169 +- pkg/core/gvisorstack.go | 10 - pkg/dns/dns.go | 4 + pkg/dns/dns_linux.go | 130 +- vendor/filippo.io/edwards25519/LICENSE | 27 + vendor/filippo.io/edwards25519/README.md | 14 + vendor/filippo.io/edwards25519/doc.go | 20 + .../filippo.io/edwards25519/edwards25519.go | 427 ++ vendor/filippo.io/edwards25519/extra.go | 349 ++ .../edwards25519}/field/fe.go | 42 +- .../edwards25519}/field/fe_amd64.go | 1 + .../edwards25519}/field/fe_amd64.s | 1 + .../edwards25519}/field/fe_amd64_noasm.go | 1 + .../edwards25519}/field/fe_arm64.go | 1 + .../edwards25519}/field/fe_arm64.s | 0 .../edwards25519}/field/fe_arm64_noasm.go | 1 + .../filippo.io/edwards25519/field/fe_extra.go | 50 + .../edwards25519}/field/fe_generic.go | 6 +- vendor/filippo.io/edwards25519/scalar.go | 343 ++ vendor/filippo.io/edwards25519/scalar_fiat.go | 1147 ++++++ vendor/filippo.io/edwards25519/scalarmult.go | 214 + vendor/filippo.io/edwards25519/tables.go | 129 + vendor/github.com/alexbrainman/sspi/LICENSE | 27 + vendor/github.com/alexbrainman/sspi/README.md | 1 + vendor/github.com/alexbrainman/sspi/buffer.go | 57 + .../sspi/internal/common/common.go | 152 + .../github.com/alexbrainman/sspi/mksyscall.go | 7 + .../alexbrainman/sspi/negotiate/negotiate.go | 368 ++ vendor/github.com/alexbrainman/sspi/sspi.go | 226 ++ .../github.com/alexbrainman/sspi/syscall.go | 174 + .../alexbrainman/sspi/zsyscall_windows.go | 152 + .../bits-and-blooms/bitset/.gitignore | 26 + .../bits-and-blooms/bitset/.travis.yml | 37 + .../github.com/bits-and-blooms/bitset/LICENSE | 27 + .../bits-and-blooms/bitset/README.md | 159 + .../bits-and-blooms/bitset/SECURITY.md | 5 + .../bitset/azure-pipelines.yml | 39 + .../bits-and-blooms/bitset/bitset.go | 1184 ++++++ .../bits-and-blooms/bitset/popcnt.go | 53 + .../bits-and-blooms/bitset/popcnt_19.go | 62 + .../bits-and-blooms/bitset/popcnt_amd64.go | 68 + .../bits-and-blooms/bitset/popcnt_amd64.s | 104 + .../bits-and-blooms/bitset/popcnt_generic.go | 25 + .../bits-and-blooms/bitset/select.go | 45 + .../bitset/trailing_zeros_18.go | 15 + .../bitset/trailing_zeros_19.go | 10 + vendor/github.com/coreos/go-iptables/LICENSE | 191 + vendor/github.com/coreos/go-iptables/NOTICE | 5 + .../coreos/go-iptables/iptables/iptables.go | 745 ++++ .../coreos/go-iptables/iptables/lock.go | 84 + vendor/github.com/dblohm7/wingoes/.gitignore | 19 + vendor/github.com/dblohm7/wingoes/LICENSE | 29 + vendor/github.com/dblohm7/wingoes/README.md | 2 + vendor/github.com/dblohm7/wingoes/error.go | 329 ++ vendor/github.com/dblohm7/wingoes/guid.go | 15 + .../dblohm7/wingoes/guid_notwindows.go | 17 + .../dblohm7/wingoes/guid_windows.go | 24 + vendor/github.com/dblohm7/wingoes/hresult.go | 12 + .../github.com/dblohm7/wingoes/osversion.go | 199 + vendor/github.com/dblohm7/wingoes/time.go | 29 + vendor/github.com/dblohm7/wingoes/util.go | 80 + vendor/github.com/docker/docker/AUTHORS | 9 + .../github.com/docker/docker/api/swagger.yaml | 216 +- .../docker/docker/api/types/types.go | 26 +- .../docker/docker/pkg/system/stat_illumos.go | 15 + .../github.com/fxamacker/cbor/v2/.gitignore | 12 + .../fxamacker/cbor/v2/.golangci.yml | 77 + .../fxamacker/cbor/v2/CODE_OF_CONDUCT.md | 133 + .../fxamacker/cbor/v2/CONTRIBUTING.md | 41 + vendor/github.com/fxamacker/cbor/v2/LICENSE | 21 + vendor/github.com/fxamacker/cbor/v2/README.md | 674 ++++ .../github.com/fxamacker/cbor/v2/SECURITY.md | 7 + .../fxamacker/cbor/v2/bytestring.go | 63 + vendor/github.com/fxamacker/cbor/v2/cache.go | 324 ++ vendor/github.com/fxamacker/cbor/v2/decode.go | 2440 ++++++++++++ .../github.com/fxamacker/cbor/v2/diagnose.go | 741 ++++ vendor/github.com/fxamacker/cbor/v2/doc.go | 129 + vendor/github.com/fxamacker/cbor/v2/encode.go | 1608 ++++++++ .../fxamacker/cbor/v2/encode_map.go | 79 + .../fxamacker/cbor/v2/encode_map_go117.go | 51 + .../fxamacker/cbor/v2/simplevalue.go | 69 + vendor/github.com/fxamacker/cbor/v2/stream.go | 277 ++ .../fxamacker/cbor/v2/structfields.go | 252 ++ vendor/github.com/fxamacker/cbor/v2/tag.go | 297 ++ vendor/github.com/fxamacker/cbor/v2/valid.go | 318 ++ .../github.com/gaissmai/bart/CONTRIBUTING.md | 1 + vendor/github.com/gaissmai/bart/LICENSE | 21 + vendor/github.com/gaissmai/bart/README.md | 123 + vendor/github.com/gaissmai/bart/base_index.go | 621 +++ vendor/github.com/gaissmai/bart/dumper.go | 205 + vendor/github.com/gaissmai/bart/jsonify.go | 74 + vendor/github.com/gaissmai/bart/node.go | 800 ++++ vendor/github.com/gaissmai/bart/stringify.go | 213 + vendor/github.com/gaissmai/bart/table.go | 821 ++++ .../go-json-experiment/json/AUTHORS | 3 + .../go-json-experiment/json/CONTRIBUTORS | 3 + .../go-json-experiment/json/LICENSE | 27 + .../go-json-experiment/json/README.md | 177 + .../go-json-experiment/json/api.png | Bin 0 -> 154576 bytes .../go-json-experiment/json/arshal.go | 531 +++ .../go-json-experiment/json/arshal_any.go | 263 ++ .../go-json-experiment/json/arshal_default.go | 1671 ++++++++ .../go-json-experiment/json/arshal_funcs.go | 402 ++ .../go-json-experiment/json/arshal_inlined.go | 226 ++ .../go-json-experiment/json/arshal_methods.go | 259 ++ .../go-json-experiment/json/arshal_time.go | 621 +++ .../json/benchmark-marshal-concrete.png | Bin 0 -> 24890 bytes .../json/benchmark-marshal-interface.png | Bin 0 -> 24868 bytes .../json/benchmark-marshal-rawvalue.png | Bin 0 -> 25032 bytes .../json/benchmark-unmarshal-concrete.png | Bin 0 -> 25104 bytes .../json/benchmark-unmarshal-interface.png | Bin 0 -> 24214 bytes .../json/benchmark-unmarshal-rawvalue.png | Bin 0 -> 24810 bytes .../github.com/go-json-experiment/json/doc.go | 170 + .../go-json-experiment/json/errors.go | 126 + .../go-json-experiment/json/fields.go | 547 +++ .../go-json-experiment/json/fold.go | 56 + .../go-json-experiment/json/intern.go | 86 + .../json/internal/internal.go | 14 + .../json/internal/jsonflags/flags.go | 184 + .../json/internal/jsonopts/options.go | 190 + .../json/internal/jsonwire/decode.go | 640 +++ .../json/internal/jsonwire/encode.go | 234 ++ .../json/internal/jsonwire/wire.go | 169 + .../json/jsontext/decode.go | 1058 +++++ .../go-json-experiment/json/jsontext/doc.go | 105 + .../json/jsontext/encode.go | 900 +++++ .../json/jsontext/errors.go | 60 + .../json/jsontext/export.go | 83 + .../json/jsontext/options.go | 178 + .../go-json-experiment/json/jsontext/pools.go | 150 + .../go-json-experiment/json/jsontext/quote.go | 31 + .../go-json-experiment/json/jsontext/state.go | 715 ++++ .../go-json-experiment/json/jsontext/token.go | 525 +++ .../go-json-experiment/json/jsontext/value.go | 305 ++ .../go-json-experiment/json/options.go | 273 ++ vendor/github.com/go-logr/logr/README.md | 1 + vendor/github.com/go-logr/logr/funcr/funcr.go | 185 +- vendor/github.com/godbus/dbus/v5/.cirrus.yml | 10 + .../github.com/godbus/dbus/v5/.golangci.yml | 7 + .../github.com/godbus/dbus/v5/CONTRIBUTING.md | 50 + vendor/github.com/godbus/dbus/v5/LICENSE | 25 + vendor/github.com/godbus/dbus/v5/MAINTAINERS | 3 + vendor/github.com/godbus/dbus/v5/README.md | 47 + vendor/github.com/godbus/dbus/v5/SECURITY.md | 13 + vendor/github.com/godbus/dbus/v5/auth.go | 257 ++ .../godbus/dbus/v5/auth_anonymous.go | 16 + .../godbus/dbus/v5/auth_external.go | 26 + vendor/github.com/godbus/dbus/v5/auth_sha1.go | 102 + vendor/github.com/godbus/dbus/v5/call.go | 66 + vendor/github.com/godbus/dbus/v5/conn.go | 995 +++++ .../github.com/godbus/dbus/v5/conn_darwin.go | 36 + .../github.com/godbus/dbus/v5/conn_other.go | 90 + vendor/github.com/godbus/dbus/v5/conn_unix.go | 18 + .../github.com/godbus/dbus/v5/conn_windows.go | 13 + vendor/github.com/godbus/dbus/v5/dbus.go | 427 ++ vendor/github.com/godbus/dbus/v5/decoder.go | 381 ++ .../godbus/dbus/v5/default_handler.go | 338 ++ vendor/github.com/godbus/dbus/v5/doc.go | 70 + vendor/github.com/godbus/dbus/v5/encoder.go | 235 ++ vendor/github.com/godbus/dbus/v5/escape.go | 84 + vendor/github.com/godbus/dbus/v5/export.go | 458 +++ vendor/github.com/godbus/dbus/v5/homedir.go | 25 + vendor/github.com/godbus/dbus/v5/match.go | 89 + vendor/github.com/godbus/dbus/v5/message.go | 393 ++ vendor/github.com/godbus/dbus/v5/object.go | 181 + vendor/github.com/godbus/dbus/v5/sequence.go | 24 + .../godbus/dbus/v5/sequential_handler.go | 125 + .../godbus/dbus/v5/server_interfaces.go | 107 + vendor/github.com/godbus/dbus/v5/sig.go | 296 ++ .../godbus/dbus/v5/transport_darwin.go | 6 + .../godbus/dbus/v5/transport_generic.go | 52 + .../godbus/dbus/v5/transport_nonce_tcp.go | 40 + .../godbus/dbus/v5/transport_tcp.go | 41 + .../godbus/dbus/v5/transport_unix.go | 284 ++ .../dbus/v5/transport_unixcred_dragonfly.go | 95 + .../dbus/v5/transport_unixcred_freebsd.go | 94 + .../dbus/v5/transport_unixcred_linux.go | 25 + .../dbus/v5/transport_unixcred_netbsd.go | 14 + .../dbus/v5/transport_unixcred_openbsd.go | 14 + .../godbus/dbus/v5/transport_zos.go | 6 + vendor/github.com/godbus/dbus/v5/variant.go | 150 + .../godbus/dbus/v5/variant_lexer.go | 284 ++ .../godbus/dbus/v5/variant_parser.go | 815 ++++ .../gnostic-models/compiler/extensions.go | 8 +- .../gnostic-models/extensions/extensions.go | 6 +- .../openapiv3/annotations.pb.go | 182 + .../openapiv3/annotations.proto | 56 + .../google/nftables/CONTRIBUTING.md | 23 + .../google/nftables}/LICENSE | 1 + vendor/github.com/google/nftables/README.md | 24 + .../nftables/alignedbuff/alignedbuff.go | 300 ++ .../google/nftables/binaryutil/binaryutil.go | 125 + vendor/github.com/google/nftables/chain.go | 328 ++ .../google/nftables/compat_policy.go | 89 + vendor/github.com/google/nftables/conn.go | 341 ++ vendor/github.com/google/nftables/counter.go | 69 + vendor/github.com/google/nftables/doc.go | 16 + .../google/nftables/expr/bitwise.go | 102 + .../google/nftables/expr/byteorder.go | 59 + .../google/nftables/expr/connlimit.go | 70 + .../google/nftables/expr/counter.go | 60 + vendor/github.com/google/nftables/expr/ct.go | 115 + vendor/github.com/google/nftables/expr/dup.go | 67 + .../github.com/google/nftables/expr/dynset.go | 149 + .../github.com/google/nftables/expr/expr.go | 430 ++ .../github.com/google/nftables/expr/exthdr.go | 102 + vendor/github.com/google/nftables/expr/fib.go | 128 + .../google/nftables/expr/flow_offload.go | 59 + .../github.com/google/nftables/expr/hash.go | 94 + .../google/nftables/expr/immediate.go | 79 + .../github.com/google/nftables/expr/limit.go | 128 + vendor/github.com/google/nftables/expr/log.go | 150 + .../github.com/google/nftables/expr/lookup.go | 85 + .../github.com/google/nftables/expr/match.go | 75 + vendor/github.com/google/nftables/expr/nat.go | 132 + .../google/nftables/expr/notrack.go} | 35 +- .../github.com/google/nftables/expr/numgen.go | 78 + .../github.com/google/nftables/expr/objref.go | 60 + .../google/nftables/expr/payload.go | 131 + .../github.com/google/nftables/expr/queue.go | 81 + .../github.com/google/nftables/expr/quota.go | 76 + .../github.com/google/nftables/expr/range.go | 124 + .../google/nftables/expr/redirect.go | 71 + .../github.com/google/nftables/expr/reject.go | 59 + vendor/github.com/google/nftables/expr/rt.go | 55 + .../github.com/google/nftables/expr/socket.go | 89 + .../github.com/google/nftables/expr/target.go | 79 + .../github.com/google/nftables/expr/tproxy.go | 82 + .../google/nftables/expr/verdict.go | 128 + .../github.com/google/nftables/flowtable.go | 306 ++ .../internal/parseexprfunc/parseexprfunc.go | 10 + vendor/github.com/google/nftables/monitor.go | 319 ++ vendor/github.com/google/nftables/obj.go | 241 ++ vendor/github.com/google/nftables/quota.go | 80 + vendor/github.com/google/nftables/rule.go | 270 ++ vendor/github.com/google/nftables/set.go | 937 +++++ vendor/github.com/google/nftables/table.go | 212 + vendor/github.com/google/nftables/util.go | 89 + vendor/github.com/google/nftables/xt/info.go | 94 + .../google/nftables/xt/match_addrtype.go | 89 + .../google/nftables/xt/match_conntrack.go | 260 ++ .../google/nftables/xt/match_tcp.go | 74 + .../google/nftables/xt/match_udp.go | 57 + .../google/nftables/xt/target_dnat.go | 106 + .../nftables/xt/target_masquerade_ip.go | 86 + .../github.com/google/nftables/xt/unknown.go | 17 + vendor/github.com/google/nftables/xt/util.go | 64 + vendor/github.com/google/nftables/xt/xt.go | 48 + .../hdevalence/ed25519consensus/LICENSE | 28 + .../hdevalence/ed25519consensus/README.md | 43 + .../hdevalence/ed25519consensus/batch.go | 151 + .../hdevalence/ed25519consensus/ed25519.go | 67 + .../github.com/illarion/gonotify/.gitignore | 8 + .../github.com/illarion/gonotify/.travis.yml | 4 + vendor/github.com/illarion/gonotify/LICENSE | 21 + vendor/github.com/illarion/gonotify/README.md | 23 + .../illarion/gonotify/dirwatcher.go | 160 + vendor/github.com/illarion/gonotify/event.go | 105 + .../illarion/gonotify/filewatcher.go | 84 + .../github.com/illarion/gonotify/inotify.go | 144 + vendor/github.com/josharian/native/doc.go | 8 + .../josharian/native/endian_generic.go | 22 + vendor/github.com/josharian/native/license | 7 + vendor/github.com/josharian/native/readme.md | 12 + .../jsimonetti/rtnetlink/.gitignore | 1 + .../jsimonetti/rtnetlink/LICENSE.md | 10 + .../jsimonetti/rtnetlink/Makefile.fuzz | 32 + .../github.com/jsimonetti/rtnetlink/README.md | 43 + .../jsimonetti/rtnetlink/address.go | 269 ++ .../github.com/jsimonetti/rtnetlink/conn.go | 197 + vendor/github.com/jsimonetti/rtnetlink/doc.go | 27 + .../github.com/jsimonetti/rtnetlink/endian.go | 13 + .../jsimonetti/rtnetlink/fuzz-shell.nix | 15 + .../rtnetlink/internal/unix/types_linux.go | 150 + .../rtnetlink/internal/unix/types_other.go | 146 + .../github.com/jsimonetti/rtnetlink/link.go | 622 +++ .../github.com/jsimonetti/rtnetlink/neigh.go | 226 ++ .../github.com/jsimonetti/rtnetlink/route.go | 626 +++ .../github.com/jsimonetti/rtnetlink/rule.go | 394 ++ vendor/github.com/mdlayher/netlink/.gitignore | 4 + .../github.com/mdlayher/netlink/CHANGELOG.md | 174 + vendor/github.com/mdlayher/netlink/LICENSE.md | 9 + vendor/github.com/mdlayher/netlink/README.md | 175 + vendor/github.com/mdlayher/netlink/align.go | 37 + .../github.com/mdlayher/netlink/attribute.go | 707 ++++ vendor/github.com/mdlayher/netlink/conn.go | 593 +++ .../github.com/mdlayher/netlink/conn_linux.go | 251 ++ .../mdlayher/netlink/conn_others.go | 30 + vendor/github.com/mdlayher/netlink/debug.go | 69 + vendor/github.com/mdlayher/netlink/doc.go | 33 + vendor/github.com/mdlayher/netlink/errors.go | 138 + vendor/github.com/mdlayher/netlink/fuzz.go | 82 + vendor/github.com/mdlayher/netlink/message.go | 347 ++ .../github.com/mdlayher/netlink/nlenc/doc.go | 15 + .../github.com/mdlayher/netlink/nlenc/int.go | 150 + .../mdlayher/netlink/nlenc/string.go | 18 + .../mdlayher/netlink/nltest/errors_others.go | 8 + .../mdlayher/netlink/nltest/errors_unix.go | 11 + .../mdlayher/netlink/nltest/nltest.go | 207 + .../github.com/mdlayher/socket/CHANGELOG.md | 89 + vendor/github.com/mdlayher/socket/LICENSE.md | 9 + vendor/github.com/mdlayher/socket/README.md | 23 + vendor/github.com/mdlayher/socket/accept.go | 23 + vendor/github.com/mdlayher/socket/accept4.go | 15 + vendor/github.com/mdlayher/socket/conn.go | 894 +++++ .../github.com/mdlayher/socket/conn_linux.go | 118 + vendor/github.com/mdlayher/socket/doc.go | 13 + .../github.com/mdlayher/socket/netns_linux.go | 150 + .../mdlayher/socket/netns_others.go | 14 + .../mdlayher/socket/setbuffer_linux.go | 24 + .../mdlayher/socket/setbuffer_others.go | 16 + .../mdlayher/socket/typ_cloexec_nonblock.go | 12 + vendor/github.com/mdlayher/socket/typ_none.go | 11 + vendor/github.com/spf13/cobra/.golangci.yml | 21 +- vendor/github.com/spf13/cobra/active_help.go | 13 +- vendor/github.com/spf13/cobra/args.go | 4 +- .../spf13/cobra/bash_completions.go | 23 +- vendor/github.com/spf13/cobra/cobra.go | 2 - vendor/github.com/spf13/cobra/command.go | 51 +- vendor/github.com/spf13/cobra/completions.go | 62 +- vendor/github.com/spf13/cobra/flag_groups.go | 34 +- .../spf13/cobra/powershell_completions.go | 4 +- .../github.com/tailscale/netlink/.gitignore | 1 + .../github.com/tailscale/netlink/.travis.yml | 20 + .../github.com/tailscale/netlink/CHANGELOG.md | 5 + vendor/github.com/tailscale/netlink/LICENSE | 192 + vendor/github.com/tailscale/netlink/Makefile | 30 + vendor/github.com/tailscale/netlink/README.md | 92 + vendor/github.com/tailscale/netlink/addr.go | 57 + .../tailscale/netlink/addr_linux.go | 414 ++ .../github.com/tailscale/netlink/bpf_linux.go | 77 + .../tailscale/netlink/bridge_linux.go | 112 + vendor/github.com/tailscale/netlink/class.go | 239 ++ .../tailscale/netlink/class_linux.go | 395 ++ .../tailscale/netlink/conntrack_linux.go | 537 +++ .../netlink/conntrack_unspecified.go | 53 + .../tailscale/netlink/devlink_linux.go | 728 ++++ vendor/github.com/tailscale/netlink/filter.go | 325 ++ .../tailscale/netlink/filter_linux.go | 949 +++++ vendor/github.com/tailscale/netlink/fou.go | 21 + .../github.com/tailscale/netlink/fou_linux.go | 211 + .../tailscale/netlink/fou_unspecified.go | 15 + .../tailscale/netlink/genetlink_linux.go | 171 + .../netlink/genetlink_unspecified.go | 25 + .../github.com/tailscale/netlink/gtp_linux.go | 239 ++ .../tailscale/netlink/handle_linux.go | 168 + .../tailscale/netlink/handle_unspecified.go | 276 ++ .../github.com/tailscale/netlink/inet_diag.go | 31 + .../tailscale/netlink/ioctl_linux.go | 90 + .../tailscale/netlink/ipset_linux.go | 504 +++ vendor/github.com/tailscale/netlink/link.go | 1315 +++++++ .../tailscale/netlink/link_linux.go | 3457 +++++++++++++++++ .../tailscale/netlink/link_tuntap_linux.go | 14 + vendor/github.com/tailscale/netlink/neigh.go | 33 + .../tailscale/netlink/neigh_linux.go | 452 +++ .../github.com/tailscale/netlink/netlink.go | 40 + .../tailscale/netlink/netlink_linux.go | 11 + .../tailscale/netlink/netlink_unspecified.go | 257 ++ .../tailscale/netlink/netns_linux.go | 141 + .../tailscale/netlink/netns_unspecified.go | 19 + vendor/github.com/tailscale/netlink/order.go | 32 + .../github.com/tailscale/netlink/protinfo.go | 62 + .../tailscale/netlink/protinfo_linux.go | 74 + vendor/github.com/tailscale/netlink/qdisc.go | 366 ++ .../tailscale/netlink/qdisc_linux.go | 708 ++++ .../tailscale/netlink/rdma_link_linux.go | 331 ++ vendor/github.com/tailscale/netlink/route.go | 209 + .../tailscale/netlink/route_linux.go | 1571 ++++++++ .../tailscale/netlink/route_unspecified.go | 21 + vendor/github.com/tailscale/netlink/rule.go | 103 + .../tailscale/netlink/rule_linux.go | 294 ++ vendor/github.com/tailscale/netlink/socket.go | 27 + .../tailscale/netlink/socket_linux.go | 291 ++ vendor/github.com/tailscale/netlink/tcp.go | 84 + .../github.com/tailscale/netlink/tcp_linux.go | 353 ++ vendor/github.com/tailscale/netlink/xfrm.go | 75 + .../tailscale/netlink/xfrm_monitor_linux.go | 101 + .../tailscale/netlink/xfrm_policy.go | 97 + .../tailscale/netlink/xfrm_policy_linux.go | 265 ++ .../tailscale/netlink/xfrm_state.go | 131 + .../tailscale/netlink/xfrm_state_linux.go | 477 +++ vendor/github.com/vishvananda/netlink/LICENSE | 192 + .../vishvananda/netlink/nl/addr_linux.go | 71 + .../vishvananda/netlink/nl/bridge_linux.go | 74 + .../vishvananda/netlink/nl/conntrack_linux.go | 219 ++ .../vishvananda/netlink/nl/devlink_linux.go | 96 + .../vishvananda/netlink/nl/genetlink_linux.go | 89 + .../vishvananda/netlink/nl/ipset_linux.go | 222 ++ .../vishvananda/netlink/nl/link_linux.go | 720 ++++ .../vishvananda/netlink/nl/lwt_linux.go | 29 + .../vishvananda/netlink/nl/mpls_linux.go | 36 + .../vishvananda/netlink/nl/nl_linux.go | 900 +++++ .../vishvananda/netlink/nl/nl_unspecified.go | 11 + .../netlink/nl/parse_attr_linux.go | 79 + .../vishvananda/netlink/nl/rdma_link_linux.go | 39 + .../vishvananda/netlink/nl/route_linux.go | 107 + .../vishvananda/netlink/nl/seg6_linux.go | 154 + .../vishvananda/netlink/nl/seg6local_linux.go | 76 + .../vishvananda/netlink/nl/syscall.go | 76 + .../vishvananda/netlink/nl/tc_linux.go | 1119 ++++++ .../vishvananda/netlink/nl/xfrm_linux.go | 306 ++ .../netlink/nl/xfrm_monitor_linux.go | 32 + .../netlink/nl/xfrm_policy_linux.go | 119 + .../netlink/nl/xfrm_state_linux.go | 334 ++ .../vishvananda/netns/.golangci.yml | 2 + vendor/github.com/vishvananda/netns/LICENSE | 192 + vendor/github.com/vishvananda/netns/README.md | 51 + vendor/github.com/vishvananda/netns/doc.go | 9 + .../vishvananda/netns/netns_linux.go | 283 ++ .../vishvananda/netns/netns_others.go | 60 + .../vishvananda/netns/nshandle_linux.go | 73 + .../vishvananda/netns/nshandle_others.go | 45 + vendor/github.com/x448/float16/.travis.yml | 13 + vendor/github.com/x448/float16/LICENSE | 22 + vendor/github.com/x448/float16/README.md | 133 + vendor/github.com/x448/float16/float16.go | 302 ++ vendor/go4.org/mem/LICENSE | 202 + vendor/go4.org/mem/README.md | 3 + vendor/go4.org/mem/fields.go | 103 + vendor/go4.org/mem/fold.go | 132 + vendor/go4.org/mem/mem.go | 313 ++ vendor/go4.org/netipx/.gitignore | 3 + vendor/go4.org/netipx/.gitmodules | 3 + vendor/go4.org/netipx/AUTHORS | 4 + vendor/go4.org/netipx/LICENSE | 27 + vendor/go4.org/netipx/README.md | 26 + vendor/go4.org/netipx/ipset.go | 498 +++ vendor/go4.org/netipx/mask6.go | 141 + vendor/go4.org/netipx/netipx.go | 584 +++ vendor/go4.org/netipx/uint128.go | 106 + vendor/golang.org/x/crypto/argon2/argon2.go | 283 ++ vendor/golang.org/x/crypto/argon2/blake2b.go | 53 + .../x/crypto/argon2/blamka_amd64.go | 60 + .../golang.org/x/crypto/argon2/blamka_amd64.s | 243 ++ .../x/crypto/argon2/blamka_generic.go | 163 + .../golang.org/x/crypto/argon2/blamka_ref.go | 15 + vendor/golang.org/x/crypto/bcrypt/bcrypt.go | 2 +- vendor/golang.org/x/crypto/blake2b/blake2b.go | 291 ++ .../x/crypto/blake2b/blake2bAVX2_amd64.go | 37 + .../x/crypto/blake2b/blake2bAVX2_amd64.s | 744 ++++ .../x/crypto/blake2b/blake2b_amd64.s | 278 ++ .../x/crypto/blake2b/blake2b_generic.go | 182 + .../x/crypto/blake2b/blake2b_ref.go | 11 + vendor/golang.org/x/crypto/blake2b/blake2x.go | 177 + .../golang.org/x/crypto/blake2b/register.go | 30 + vendor/golang.org/x/crypto/blake2s/blake2s.go | 10 +- .../golang.org/x/crypto/blake2s/register.go | 21 - vendor/golang.org/x/crypto/blowfish/cipher.go | 2 +- .../chacha20poly1305/chacha20poly1305.go | 2 +- .../x/crypto/cryptobyte/asn1/asn1.go | 2 +- .../golang.org/x/crypto/cryptobyte/string.go | 2 +- .../x/crypto/curve25519/curve25519.go | 39 +- .../x/crypto/curve25519/curve25519_compat.go | 105 - .../x/crypto/curve25519/curve25519_go120.go | 46 - .../x/crypto/curve25519/internal/field/README | 7 - .../curve25519/internal/field/sync.checkpoint | 1 - .../crypto/curve25519/internal/field/sync.sh | 19 - vendor/golang.org/x/crypto/ed25519/ed25519.go | 4 +- vendor/golang.org/x/crypto/hkdf/hkdf.go | 2 +- vendor/golang.org/x/crypto/md4/md4.go | 2 +- vendor/golang.org/x/crypto/nacl/box/box.go | 182 + .../x/crypto/nacl/secretbox/secretbox.go | 173 + vendor/golang.org/x/crypto/pbkdf2/pbkdf2.go | 2 +- .../x/crypto/poly1305/poly1305_compat.go | 2 +- .../x/crypto/salsa20/salsa/hsalsa20.go | 146 + .../x/crypto/salsa20/salsa/salsa208.go | 201 + .../x/crypto/salsa20/salsa/salsa20_amd64.go | 23 + .../x/crypto/salsa20/salsa/salsa20_amd64.s | 880 +++++ .../x/crypto/salsa20/salsa/salsa20_noasm.go | 14 + .../x/crypto/salsa20/salsa/salsa20_ref.go | 233 ++ vendor/golang.org/x/crypto/scrypt/scrypt.go | 2 +- vendor/golang.org/x/crypto/ssh/client_auth.go | 4 + vendor/golang.org/x/crypto/ssh/doc.go | 2 +- vendor/golang.org/x/crypto/ssh/keys.go | 8 + vendor/golang.org/x/crypto/ssh/server.go | 30 + vendor/golang.org/x/mod/modfile/rule.go | 106 +- vendor/golang.org/x/mod/modfile/work.go | 52 +- .../x/net/dns/dnsmessage/message.go | 2712 +++++++++++++ .../golang.org/x/net/http/httpproxy/proxy.go | 367 ++ vendor/golang.org/x/net/http2/http2.go | 19 +- vendor/golang.org/x/net/http2/server.go | 94 +- vendor/golang.org/x/net/http2/testsync.go | 331 -- vendor/golang.org/x/net/http2/timer.go | 20 + vendor/golang.org/x/net/http2/transport.go | 314 +- .../x/net/http2/writesched_priority.go | 4 +- vendor/golang.org/x/net/proxy/per_host.go | 8 +- vendor/golang.org/x/net/websocket/hybi.go | 5 +- .../golang.org/x/net/websocket/websocket.go | 7 +- vendor/golang.org/x/sys/unix/mkerrors.sh | 2 + vendor/golang.org/x/sys/unix/mremap.go | 5 + .../golang.org/x/sys/unix/syscall_darwin.go | 12 + vendor/golang.org/x/sys/unix/syscall_unix.go | 9 + vendor/golang.org/x/sys/unix/zerrors_linux.go | 20 +- .../x/sys/unix/zerrors_linux_386.go | 1 + .../x/sys/unix/zerrors_linux_amd64.go | 1 + .../x/sys/unix/zerrors_linux_arm64.go | 1 + .../x/sys/unix/zsyscall_darwin_amd64.go | 33 + .../x/sys/unix/zsyscall_darwin_amd64.s | 10 + .../x/sys/unix/zsyscall_darwin_arm64.go | 33 + .../x/sys/unix/zsyscall_darwin_arm64.s | 10 + vendor/golang.org/x/sys/unix/ztypes_linux.go | 37 +- .../x/sys/windows/security_windows.go | 25 +- .../x/sys/windows/svc/mgr/config.go | 180 + .../golang.org/x/sys/windows/svc/mgr/mgr.go | 208 + .../x/sys/windows/svc/mgr/recovery.go | 162 + .../x/sys/windows/svc/mgr/service.go | 124 + .../golang.org/x/sys/windows/svc/security.go | 100 + .../golang.org/x/sys/windows/svc/service.go | 315 ++ .../x/sys/windows/zsyscall_windows.go | 18 + .../x/tools/go/ast/astutil/enclosing.go | 24 +- .../golang.org/x/tools/go/ast/astutil/util.go | 1 + .../tools/go/internal/packagesdriver/sizes.go | 53 - vendor/golang.org/x/tools/go/packages/doc.go | 8 - .../x/tools/go/packages/external.go | 22 +- .../golang.org/x/tools/go/packages/golist.go | 126 +- .../x/tools/go/packages/packages.go | 95 +- .../x/tools/go/types/objectpath/objectpath.go | 59 +- .../x/tools/internal/gocommand/invoke.go | 113 +- .../x/tools/internal/imports/fix.go | 357 +- .../x/tools/internal/imports/mod.go | 8 +- .../x/tools/internal/stdlib/manifest.go | 111 + .../x/tools/internal/typesinternal/types.go | 15 + .../x/tools/internal/versions/types_go122.go | 2 +- vendor/golang.org/x/xerrors/LICENSE | 4 +- vendor/golang.zx2c4.com/wintun/dll.go | 4 +- vendor/golang.zx2c4.com/wintun/session.go | 4 +- vendor/golang.zx2c4.com/wintun/wintun.go | 19 +- .../gvisor/pkg/cpuid/cpuid_amd64.go | 8 +- .../gvisor/pkg/cpuid/cpuid_arm64.go | 2 +- .../goid/{goid_amd64.s => goid_122_amd64.s} | 2 + .../goid/{goid_arm64.s => goid_122_arm64.s} | 2 + .../gvisor/pkg/goid/goid_123_amd64.s | 26 + .../gvisor/pkg/goid/goid_123_arm64.s | 26 + vendor/gvisor.dev/gvisor/pkg/rand/rng.go | 2 +- vendor/gvisor.dev/gvisor/pkg/state/decode.go | 5 +- vendor/gvisor.dev/gvisor/pkg/state/encode.go | 7 +- vendor/gvisor.dev/gvisor/pkg/state/state.go | 5 +- .../gvisor.dev/gvisor/pkg/state/wire/wire.go | 174 +- .../gvisor/pkg/sync/runtime_exectracer2.go | 2 - vendor/gvisor.dev/gvisor/pkg/tcpip/errors.go | 15 + .../gvisor/pkg/tcpip/errors_linux.go | 74 + .../gvisor/pkg/tcpip/header/ipv4.go | 17 +- .../gvisor/pkg/tcpip/header/ipv6.go | 12 + .../pkg/tcpip/header/ndp_neighbor_advert.go | 2 +- .../pkg/tcpip/header/ndp_neighbor_solicit.go | 2 +- .../pkg/tcpip/header/ndp_router_advert.go | 2 +- .../pkg/tcpip/header/ndp_router_solicit.go | 2 +- .../gvisor/pkg/tcpip/link/channel/channel.go | 38 +- .../link/channel/channel_state_autogen.go | 41 + .../gvisor/pkg/tcpip/link/nested/nested.go | 26 +- .../tcpip/link/nested/nested_state_autogen.go | 41 + .../tcpip/link/packetsocket/packetsocket.go | 1 + .../packetsocket_state_autogen.go | 35 + .../internal/fragmentation/fragmentation.go | 6 +- .../fragmentation_state_autogen.go | 176 + .../internal/fragmentation/reassembler.go | 4 +- .../ip/duplicate_address_detection.go | 12 +- .../internal/ip/generic_multicast_protocol.go | 21 +- .../network/internal/ip/ip_state_autogen.go | 376 ++ .../pkg/tcpip/network/internal/ip/stats.go | 4 + .../multicast/multicast_state_autogen.go | 134 + .../network/internal/multicast/route_table.go | 14 +- .../gvisor/pkg/tcpip/network/ipv4/icmp.go | 3 +- .../gvisor/pkg/tcpip/network/ipv4/igmp.go | 4 + .../gvisor/pkg/tcpip/network/ipv4/ipv4.go | 50 +- .../tcpip/network/ipv4/ipv4_state_autogen.go | 540 +++ .../gvisor/pkg/tcpip/network/ipv4/stats.go | 11 + .../gvisor/pkg/tcpip/network/ipv6/icmp.go | 3 +- .../gvisor/pkg/tcpip/network/ipv6/ipv6.go | 99 +- .../tcpip/network/ipv6/ipv6_state_autogen.go | 911 +++++ .../gvisor/pkg/tcpip/network/ipv6/mld.go | 4 + .../gvisor/pkg/tcpip/network/ipv6/ndp.go | 41 +- .../gvisor/pkg/tcpip/network/ipv6/stats.go | 7 + .../gvisor/pkg/tcpip/ports/flags.go | 2 + .../gvisor/pkg/tcpip/ports/ports.go | 8 +- .../pkg/tcpip/ports/ports_state_autogen.go | 119 + .../gro_packet_list.go => route_list.go} | 86 +- .../tcpip/stack/addressable_endpoint_state.go | 37 +- .../gvisor/pkg/tcpip/stack/bridge.go | 229 ++ .../gvisor/pkg/tcpip/stack/bridge_mutex.go | 96 + .../gvisor/pkg/tcpip/stack/conntrack.go | 6 +- .../gvisor.dev/gvisor/pkg/tcpip/stack/gro.go | 747 ---- .../gvisor/pkg/tcpip/stack/icmp_rate_limit.go | 5 +- .../pkg/tcpip/stack/iptables_targets.go | 22 + .../gvisor/pkg/tcpip/stack/iptables_types.go | 2 +- .../gvisor/pkg/tcpip/stack/neighbor_cache.go | 35 +- .../gvisor.dev/gvisor/pkg/tcpip/stack/nic.go | 46 +- .../gvisor/pkg/tcpip/stack/nic_stats.go | 4 + .../gvisor.dev/gvisor/pkg/tcpip/stack/nud.go | 41 +- .../pkg/tcpip/stack/packet_buffer_list.go | 12 + .../gvisor/pkg/tcpip/stack/pending_packets.go | 35 +- .../gvisor/pkg/tcpip/stack/registration.go | 40 +- .../gvisor/pkg/tcpip/stack/route.go | 40 +- .../gvisor/pkg/tcpip/stack/stack.go | 362 +- .../pkg/tcpip/stack/stack_state_autogen.go | 1453 ++++++- .../gvisor.dev/gvisor/pkg/tcpip/stack/tcp.go | 20 + .../pkg/tcpip/stack/transport_demuxer.go | 10 +- .../gvisor.dev/gvisor/pkg/tcpip/stdclock.go | 1 + vendor/gvisor.dev/gvisor/pkg/tcpip/tcpip.go | 110 +- .../pkg/tcpip/tcpip_linux_state_autogen.go | 6 + .../gvisor/pkg/tcpip/tcpip_state_autogen.go | 1467 +++++++ vendor/gvisor.dev/gvisor/pkg/tcpip/timer.go | 9 +- .../transport/internal/network/endpoint.go | 43 +- .../pkg/tcpip/transport/raw/protocol.go | 4 + .../tcpip/transport/raw/raw_state_autogen.go | 44 + .../gvisor/pkg/tcpip/transport/tcp/connect.go | 14 +- .../gvisor/pkg/tcpip/transport/tcp/cubic.go | 102 +- .../pkg/tcpip/transport/tcp/dispatcher.go | 29 +- .../pkg/tcpip/transport/tcp/endpoint.go | 40 +- .../pkg/tcpip/transport/tcp/endpoint_state.go | 2 +- .../pkg/tcpip/transport/tcp/protocol.go | 20 +- .../gvisor/pkg/tcpip/transport/tcp/reno.go | 6 +- .../gvisor/pkg/tcpip/transport/tcp/snd.go | 72 +- .../tcpip/transport/tcp/tcp_state_autogen.go | 393 +- .../transport/tcpconntrack/tcp_conntrack.go | 9 +- .../tcpconntrack_state_autogen.go | 88 + .../pkg/tcpip/transport/udp/endpoint.go | 21 +- .../pkg/tcpip/transport/udp/protocol.go | 1 + .../tcpip/transport/udp/udp_state_autogen.go | 93 +- vendor/k8s.io/component-base/config/OWNERS | 13 - vendor/k8s.io/component-base/config/doc.go | 19 - vendor/k8s.io/component-base/config/types.go | 80 - .../config/v1alpha1/conversion.go | 53 - .../config/v1alpha1/defaults.go | 98 - .../component-base/config/v1alpha1/doc.go | 20 - .../config/v1alpha1/register.go | 31 - .../component-base/config/v1alpha1/types.go | 82 - .../v1alpha1/zz_generated.conversion.go | 133 - .../config/v1alpha1/zz_generated.deepcopy.go | 88 - .../config/zz_generated.deepcopy.go | 73 - vendor/k8s.io/klog/v2/klog.go | 76 +- vendor/k8s.io/utils/net/multi_listen.go | 195 + vendor/k8s.io/utils/trace/trace.go | 2 +- vendor/modules.txt | 204 +- .../controller-runtime/.golangci.yml | 16 +- .../sigs.k8s.io/controller-runtime/Makefile | 11 +- .../sigs.k8s.io/controller-runtime/alias.go | 8 - .../pkg/builder/controller.go | 60 +- .../controller-runtime/pkg/cache/cache.go | 78 +- .../pkg/cache/internal/cache_reader.go | 2 +- .../pkg/cache/internal/informers.go | 13 +- .../pkg/cache/multi_namespace_cache.go | 14 +- .../controller-runtime/pkg/client/client.go | 4 +- .../pkg/client/fieldowner.go | 106 + .../controller-runtime/pkg/config/config.go | 112 - .../controller-runtime/pkg/config/doc.go | 19 - .../pkg/config/v1alpha1/doc.go | 22 - .../pkg/config/v1alpha1/register.go | 43 - .../pkg/config/v1alpha1/types.go | 179 - .../config/v1alpha1/zz_generated.deepcopy.go | 157 - .../pkg/controller/controller.go | 40 +- .../controllerutil/controllerutil.go | 20 +- .../controller-runtime/pkg/event/event.go | 51 +- .../controller-runtime/pkg/handler/enqueue.go | 43 +- .../pkg/handler/enqueue_mapped.go | 42 +- .../pkg/handler/enqueue_owner.go | 48 +- .../pkg/handler/eventhandler.go | 60 +- .../pkg/internal/controller/controller.go | 35 +- .../pkg/internal/source/event_handler.go | 32 +- .../pkg/internal/source/kind.go | 58 +- .../pkg/manager/internal.go | 55 +- .../controller-runtime/pkg/manager/manager.go | 132 +- .../pkg/manager/runnable_group.go | 20 +- .../controller-runtime/pkg/manager/server.go | 74 +- .../pkg/metrics/server/server.go | 20 + .../pkg/predicate/predicate.go | 175 +- .../controller-runtime/pkg/source/source.go | 120 +- .../pkg/parser/parser.go | 212 - vendor/tailscale.com/.gitattributes | 2 + vendor/tailscale.com/.gitignore | 45 + vendor/tailscale.com/.golangci.yml | 104 + vendor/tailscale.com/ALPINE.txt | 1 + vendor/tailscale.com/AUTHORS | 17 + vendor/tailscale.com/CODEOWNERS | 1 + vendor/tailscale.com/CODE_OF_CONDUCT.md | 135 + vendor/tailscale.com/Dockerfile | 71 + vendor/tailscale.com/Dockerfile.base | 5 + vendor/tailscale.com/LICENSE | 28 + vendor/tailscale.com/Makefile | 128 + vendor/tailscale.com/PATENTS | 24 + vendor/tailscale.com/README.md | 88 + vendor/tailscale.com/SECURITY.md | 8 + vendor/tailscale.com/VERSION.txt | 1 + vendor/tailscale.com/api.md | 104 + vendor/tailscale.com/atomicfile/atomicfile.go | 51 + vendor/tailscale.com/build_dist.sh | 52 + vendor/tailscale.com/build_docker.sh | 84 + .../control/controlknobs/controlknobs.go | 191 + vendor/tailscale.com/envknob/envknob.go | 606 +++ .../tailscale.com/envknob/envknob_nottest.go | 16 + .../tailscale.com/envknob/envknob_testable.go | 23 + vendor/tailscale.com/envknob/features.go | 39 + vendor/tailscale.com/flake.lock | 78 + vendor/tailscale.com/flake.nix | 123 + vendor/tailscale.com/go.mod.sri | 1 + vendor/tailscale.com/go.toolchain.branch | 1 + vendor/tailscale.com/go.toolchain.rev | 1 + vendor/tailscale.com/header.txt | 2 + vendor/tailscale.com/health/args.go | 39 + vendor/tailscale.com/health/health.go | 1234 ++++++ vendor/tailscale.com/health/state.go | 99 + vendor/tailscale.com/health/warnings.go | 247 ++ vendor/tailscale.com/hostinfo/hostinfo.go | 477 +++ .../tailscale.com/hostinfo/hostinfo_darwin.go | 21 + .../hostinfo/hostinfo_freebsd.go | 64 + .../tailscale.com/hostinfo/hostinfo_linux.go | 177 + .../tailscale.com/hostinfo/hostinfo_uname.go | 38 + .../hostinfo/hostinfo_windows.go | 94 + .../hostinfo/packagetype_container.go | 10 + vendor/tailscale.com/hostinfo/wol.go | 106 + .../tailscale.com/logtail/backoff/backoff.go | 80 + vendor/tailscale.com/net/dns/config.go | 182 + .../net/dns/debian_resolvconf.go | 184 + vendor/tailscale.com/net/dns/direct.go | 551 +++ vendor/tailscale.com/net/dns/direct_linux.go | 114 + .../tailscale.com/net/dns/direct_notlinux.go | 10 + vendor/tailscale.com/net/dns/flush_default.go | 10 + vendor/tailscale.com/net/dns/flush_windows.go | 34 + vendor/tailscale.com/net/dns/ini.go | 30 + vendor/tailscale.com/net/dns/manager.go | 559 +++ .../tailscale.com/net/dns/manager_darwin.go | 126 + .../tailscale.com/net/dns/manager_default.go | 19 + .../tailscale.com/net/dns/manager_freebsd.go | 43 + vendor/tailscale.com/net/dns/manager_linux.go | 431 ++ .../tailscale.com/net/dns/manager_openbsd.go | 78 + .../tailscale.com/net/dns/manager_windows.go | 614 +++ vendor/tailscale.com/net/dns/nm.go | 391 ++ vendor/tailscale.com/net/dns/noop.go | 17 + vendor/tailscale.com/net/dns/nrpt_windows.go | 459 +++ vendor/tailscale.com/net/dns/openresolv.go | 115 + vendor/tailscale.com/net/dns/osconfig.go | 180 + .../net/dns/publicdns/publicdns.go | 344 ++ .../net/dns/resolvconf-workaround.sh | 62 + vendor/tailscale.com/net/dns/resolvconf.go | 30 + .../net/dns/resolvconffile/resolvconffile.go | 124 + .../net/dns/resolvconfpath_default.go | 11 + .../net/dns/resolvconfpath_gokrazy.go | 11 + vendor/tailscale.com/net/dns/resolvd.go | 128 + vendor/tailscale.com/net/dns/resolved.go | 394 ++ .../tailscale.com/net/dns/resolver/debug.go | 77 + .../net/dns/resolver/forwarder.go | 1165 ++++++ .../net/dns/resolver/macios_ext.go | 26 + .../tailscale.com/net/dns/resolver/tsdns.go | 1404 +++++++ vendor/tailscale.com/net/dns/utf.go | 55 + vendor/tailscale.com/net/dns/wsl_windows.go | 239 ++ vendor/tailscale.com/net/dnscache/dnscache.go | 693 ++++ .../net/dnscache/messagecache.go | 311 ++ vendor/tailscale.com/net/netaddr/netaddr.go | 49 + vendor/tailscale.com/net/neterror/neterror.go | 82 + .../net/neterror/neterror_linux.go | 26 + .../net/neterror/neterror_windows.go | 16 + vendor/tailscale.com/net/netknob/netknob.go | 29 + .../net/netmon/defaultroute_bsd.go | 26 + .../net/netmon/defaultroute_darwin.go | 96 + .../net/netmon/interfaces_android.go | 183 + .../net/netmon/interfaces_bsd.go | 153 + .../net/netmon/interfaces_darwin.go | 111 + .../netmon/interfaces_defaultrouteif_todo.go | 14 + .../net/netmon/interfaces_freebsd.go | 28 + .../net/netmon/interfaces_linux.go | 305 ++ .../net/netmon/interfaces_windows.go | 278 ++ vendor/tailscale.com/net/netmon/netmon.go | 626 +++ .../tailscale.com/net/netmon/netmon_darwin.go | 225 ++ .../net/netmon/netmon_freebsd.go | 56 + .../tailscale.com/net/netmon/netmon_linux.go | 290 ++ .../net/netmon/netmon_polling.go | 21 + .../net/netmon/netmon_windows.go | 190 + vendor/tailscale.com/net/netmon/polling.go | 86 + vendor/tailscale.com/net/netmon/state.go | 773 ++++ vendor/tailscale.com/net/netns/mksyscall.go | 9 + vendor/tailscale.com/net/netns/netns.go | 135 + .../tailscale.com/net/netns/netns_android.go | 75 + .../tailscale.com/net/netns/netns_darwin.go | 287 ++ .../tailscale.com/net/netns/netns_default.go | 22 + vendor/tailscale.com/net/netns/netns_dw.go | 27 + vendor/tailscale.com/net/netns/netns_linux.go | 133 + .../tailscale.com/net/netns/netns_windows.go | 224 ++ vendor/tailscale.com/net/netns/socks.go | 19 + .../net/netns/zsyscall_windows.go | 53 + .../net/sockstats/label_string.go | 35 + .../tailscale.com/net/sockstats/sockstats.go | 121 + .../net/sockstats/sockstats_noop.go | 38 + .../net/sockstats/sockstats_tsgo.go | 425 ++ .../net/sockstats/sockstats_tsgo_darwin.go | 30 + vendor/tailscale.com/net/tsaddr/tsaddr.go | 266 ++ vendor/tailscale.com/net/tsdial/dnsmap.go | 121 + vendor/tailscale.com/net/tsdial/dohclient.go | 100 + .../net/tsdial/peerapi_macios_ext.go | 52 + vendor/tailscale.com/net/tsdial/tsdial.go | 506 +++ .../net/tshttpproxy/mksyscall.go | 11 + .../net/tshttpproxy/tshttpproxy.go | 219 ++ .../net/tshttpproxy/tshttpproxy_linux.go | 24 + .../net/tshttpproxy/tshttpproxy_synology.go | 140 + .../net/tshttpproxy/tshttpproxy_windows.go | 276 ++ .../net/tshttpproxy/zsyscall_windows.go | 81 + vendor/tailscale.com/pull-toolchain.sh | 16 + vendor/tailscale.com/shell.nix | 19 + vendor/tailscale.com/staticcheck.conf | 18 + vendor/tailscale.com/syncs/locked.go | 32 + vendor/tailscale.com/syncs/pool.go | 31 + vendor/tailscale.com/syncs/shardedmap.go | 138 + vendor/tailscale.com/syncs/syncs.go | 317 ++ vendor/tailscale.com/tailcfg/c2ntypes.go | 104 + vendor/tailscale.com/tailcfg/derpmap.go | 205 + .../tailscale.com/tailcfg/proto_port_range.go | 187 + vendor/tailscale.com/tailcfg/tailcfg.go | 2813 ++++++++++++++ vendor/tailscale.com/tailcfg/tailcfg_clone.go | 806 ++++ vendor/tailscale.com/tailcfg/tailcfg_view.go | 1451 +++++++ vendor/tailscale.com/tailcfg/tka.go | 264 ++ vendor/tailscale.com/tka/aum.go | 348 ++ vendor/tailscale.com/tka/builder.go | 180 + vendor/tailscale.com/tka/deeplink.go | 221 ++ vendor/tailscale.com/tka/key.go | 159 + vendor/tailscale.com/tka/sig.go | 444 +++ vendor/tailscale.com/tka/state.go | 315 ++ vendor/tailscale.com/tka/sync.go | 246 ++ vendor/tailscale.com/tka/tailchonk.go | 852 ++++ vendor/tailscale.com/tka/tka.go | 850 ++++ vendor/tailscale.com/tsconst/interface.go | 15 + vendor/tailscale.com/tstime/jitter.go | 19 + vendor/tailscale.com/tstime/mono/mono.go | 127 + vendor/tailscale.com/tstime/rate/rate.go | 90 + vendor/tailscale.com/tstime/rate/value.go | 222 ++ vendor/tailscale.com/tstime/tstime.go | 185 + vendor/tailscale.com/types/dnstype/dnstype.go | 68 + .../types/dnstype/dnstype_clone.go | 46 + .../types/dnstype/dnstype_view.go | 73 + vendor/tailscale.com/types/ipproto/ipproto.go | 199 + vendor/tailscale.com/types/key/chal.go | 91 + vendor/tailscale.com/types/key/control.go | 68 + vendor/tailscale.com/types/key/disco.go | 192 + vendor/tailscale.com/types/key/doc.go | 6 + vendor/tailscale.com/types/key/machine.go | 264 ++ vendor/tailscale.com/types/key/nl.go | 178 + vendor/tailscale.com/types/key/node.go | 380 ++ vendor/tailscale.com/types/key/util.go | 117 + vendor/tailscale.com/types/lazy/lazy.go | 191 + vendor/tailscale.com/types/lazy/unsync.go | 99 + vendor/tailscale.com/types/logger/logger.go | 418 ++ vendor/tailscale.com/types/logger/rusage.go | 23 + .../tailscale.com/types/logger/rusage_stub.go | 11 + .../types/logger/rusage_syscall.go | 29 + .../tailscale.com/types/logger/tokenbucket.go | 63 + vendor/tailscale.com/types/netmap/netmap.go | 393 ++ vendor/tailscale.com/types/netmap/nodemut.go | 182 + vendor/tailscale.com/types/nettype/nettype.go | 65 + vendor/tailscale.com/types/opt/bool.go | 107 + vendor/tailscale.com/types/opt/value.go | 130 + vendor/tailscale.com/types/ptr/ptr.go | 10 + vendor/tailscale.com/types/structs/structs.go | 15 + vendor/tailscale.com/types/tkatype/tkatype.go | 40 + vendor/tailscale.com/types/views/views.go | 608 +++ vendor/tailscale.com/update-flake.sh | 18 + vendor/tailscale.com/util/cibuild/cibuild.go | 14 + .../util/clientmetric/clientmetric.go | 385 ++ .../tailscale.com/util/cloudenv/cloudenv.go | 209 + vendor/tailscale.com/util/cmpver/version.go | 117 + vendor/tailscale.com/util/ctxkey/key.go | 135 + vendor/tailscale.com/util/dnsname/dnsname.go | 265 ++ .../tailscale.com/util/lineread/lineread.go | 37 + vendor/tailscale.com/util/linuxfw/detector.go | 116 + vendor/tailscale.com/util/linuxfw/fake.go | 142 + vendor/tailscale.com/util/linuxfw/helpers.go | 37 + vendor/tailscale.com/util/linuxfw/iptables.go | 70 + .../util/linuxfw/iptables_runner.go | 733 ++++ vendor/tailscale.com/util/linuxfw/linuxfw.go | 182 + .../util/linuxfw/linuxfw_unsupported.go | 40 + vendor/tailscale.com/util/linuxfw/nftables.go | 292 ++ .../util/linuxfw/nftables_runner.go | 2024 ++++++++++ .../util/linuxfw/nftables_types.go | 95 + vendor/tailscale.com/util/mak/mak.go | 70 + .../tailscale.com/util/multierr/multierr.go | 136 + .../tailscale.com/util/nocasemaps/nocase.go | 116 + vendor/tailscale.com/util/race/race.go | 115 + vendor/tailscale.com/util/set/handle.go | 28 + vendor/tailscale.com/util/set/set.go | 94 + vendor/tailscale.com/util/set/slice.go | 73 + .../util/singleflight/singleflight.go | 311 ++ vendor/tailscale.com/util/slicesx/slicesx.go | 138 + vendor/tailscale.com/util/testenv/testenv.go | 21 + .../tailscale.com/util/vizerror/vizerror.go | 50 + .../util/winutil/gp/gp_windows.go | 79 + .../util/winutil/gp/mksyscall.go | 13 + .../util/winutil/gp/policylock_windows.go | 292 ++ .../util/winutil/gp/watcher_windows.go | 107 + .../util/winutil/gp/zsyscall_windows.go | 111 + .../tailscale.com/util/winutil/mksyscall.go | 21 + .../util/winutil/restartmgr_windows.go | 845 ++++ .../util/winutil/startupinfo_windows.go | 317 ++ .../util/winutil/svcdiag_windows.go | 303 ++ .../util/winutil/userprofile_windows.go | 237 ++ .../util/winutil/winenv/mksyscall.go | 15 + .../util/winutil/winenv/winenv_windows.go | 109 + .../util/winutil/winenv/zsyscall_windows.go | 77 + vendor/tailscale.com/util/winutil/winutil.go | 116 + .../util/winutil/winutil_notwindows.go | 38 + .../util/winutil/winutil_windows.go | 931 +++++ .../util/winutil/zsyscall_windows.go | 162 + vendor/tailscale.com/version-embed.go | 24 + vendor/tailscale.com/version/.gitignore | 10 + vendor/tailscale.com/version/cmdname.go | 139 + vendor/tailscale.com/version/cmdname_ios.go | 18 + vendor/tailscale.com/version/cmp.go | 193 + vendor/tailscale.com/version/distro/distro.go | 149 + vendor/tailscale.com/version/print.go | 33 + vendor/tailscale.com/version/prop.go | 260 ++ vendor/tailscale.com/version/race.go | 10 + vendor/tailscale.com/version/race_off.go | 10 + vendor/tailscale.com/version/version.go | 171 + .../wgengine/filter/filtertype/filtertype.go | 116 + .../filter/filtertype/filtertype_clone.go | 64 + 912 files changed, 144260 insertions(+), 5039 deletions(-) create mode 100644 vendor/filippo.io/edwards25519/LICENSE create mode 100644 vendor/filippo.io/edwards25519/README.md create mode 100644 vendor/filippo.io/edwards25519/doc.go create mode 100644 vendor/filippo.io/edwards25519/edwards25519.go create mode 100644 vendor/filippo.io/edwards25519/extra.go rename vendor/{golang.org/x/crypto/curve25519/internal => filippo.io/edwards25519}/field/fe.go (90%) rename vendor/{golang.org/x/crypto/curve25519/internal => filippo.io/edwards25519}/field/fe_amd64.go (93%) rename vendor/{golang.org/x/crypto/curve25519/internal => filippo.io/edwards25519}/field/fe_amd64.s (99%) rename vendor/{golang.org/x/crypto/curve25519/internal => filippo.io/edwards25519}/field/fe_amd64_noasm.go (92%) rename vendor/{golang.org/x/crypto/curve25519/internal => filippo.io/edwards25519}/field/fe_arm64.go (92%) rename vendor/{golang.org/x/crypto/curve25519/internal => filippo.io/edwards25519}/field/fe_arm64.s (100%) rename vendor/{golang.org/x/crypto/curve25519/internal => filippo.io/edwards25519}/field/fe_arm64_noasm.go (91%) create mode 100644 vendor/filippo.io/edwards25519/field/fe_extra.go rename vendor/{golang.org/x/crypto/curve25519/internal => filippo.io/edwards25519}/field/fe_generic.go (96%) create mode 100644 vendor/filippo.io/edwards25519/scalar.go create mode 100644 vendor/filippo.io/edwards25519/scalar_fiat.go create mode 100644 vendor/filippo.io/edwards25519/scalarmult.go create mode 100644 vendor/filippo.io/edwards25519/tables.go create mode 100644 vendor/github.com/alexbrainman/sspi/LICENSE create mode 100644 vendor/github.com/alexbrainman/sspi/README.md create mode 100644 vendor/github.com/alexbrainman/sspi/buffer.go create mode 100644 vendor/github.com/alexbrainman/sspi/internal/common/common.go create mode 100644 vendor/github.com/alexbrainman/sspi/mksyscall.go create mode 100644 vendor/github.com/alexbrainman/sspi/negotiate/negotiate.go create mode 100644 vendor/github.com/alexbrainman/sspi/sspi.go create mode 100644 vendor/github.com/alexbrainman/sspi/syscall.go create mode 100644 vendor/github.com/alexbrainman/sspi/zsyscall_windows.go create mode 100644 vendor/github.com/bits-and-blooms/bitset/.gitignore create mode 100644 vendor/github.com/bits-and-blooms/bitset/.travis.yml create mode 100644 vendor/github.com/bits-and-blooms/bitset/LICENSE create mode 100644 vendor/github.com/bits-and-blooms/bitset/README.md create mode 100644 vendor/github.com/bits-and-blooms/bitset/SECURITY.md create mode 100644 vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml create mode 100644 vendor/github.com/bits-and-blooms/bitset/bitset.go create mode 100644 vendor/github.com/bits-and-blooms/bitset/popcnt.go create mode 100644 vendor/github.com/bits-and-blooms/bitset/popcnt_19.go create mode 100644 vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go create mode 100644 vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s create mode 100644 vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go create mode 100644 vendor/github.com/bits-and-blooms/bitset/select.go create mode 100644 vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go create mode 100644 vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go create mode 100644 vendor/github.com/coreos/go-iptables/LICENSE create mode 100644 vendor/github.com/coreos/go-iptables/NOTICE create mode 100644 vendor/github.com/coreos/go-iptables/iptables/iptables.go create mode 100644 vendor/github.com/coreos/go-iptables/iptables/lock.go create mode 100644 vendor/github.com/dblohm7/wingoes/.gitignore create mode 100644 vendor/github.com/dblohm7/wingoes/LICENSE create mode 100644 vendor/github.com/dblohm7/wingoes/README.md create mode 100644 vendor/github.com/dblohm7/wingoes/error.go create mode 100644 vendor/github.com/dblohm7/wingoes/guid.go create mode 100644 vendor/github.com/dblohm7/wingoes/guid_notwindows.go create mode 100644 vendor/github.com/dblohm7/wingoes/guid_windows.go create mode 100644 vendor/github.com/dblohm7/wingoes/hresult.go create mode 100644 vendor/github.com/dblohm7/wingoes/osversion.go create mode 100644 vendor/github.com/dblohm7/wingoes/time.go create mode 100644 vendor/github.com/dblohm7/wingoes/util.go create mode 100644 vendor/github.com/docker/docker/pkg/system/stat_illumos.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/.gitignore create mode 100644 vendor/github.com/fxamacker/cbor/v2/.golangci.yml create mode 100644 vendor/github.com/fxamacker/cbor/v2/CODE_OF_CONDUCT.md create mode 100644 vendor/github.com/fxamacker/cbor/v2/CONTRIBUTING.md create mode 100644 vendor/github.com/fxamacker/cbor/v2/LICENSE create mode 100644 vendor/github.com/fxamacker/cbor/v2/README.md create mode 100644 vendor/github.com/fxamacker/cbor/v2/SECURITY.md create mode 100644 vendor/github.com/fxamacker/cbor/v2/bytestring.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/cache.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/decode.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/diagnose.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/doc.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/encode.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/encode_map.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/encode_map_go117.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/simplevalue.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/stream.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/structfields.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/tag.go create mode 100644 vendor/github.com/fxamacker/cbor/v2/valid.go create mode 100644 vendor/github.com/gaissmai/bart/CONTRIBUTING.md create mode 100644 vendor/github.com/gaissmai/bart/LICENSE create mode 100644 vendor/github.com/gaissmai/bart/README.md create mode 100644 vendor/github.com/gaissmai/bart/base_index.go create mode 100644 vendor/github.com/gaissmai/bart/dumper.go create mode 100644 vendor/github.com/gaissmai/bart/jsonify.go create mode 100644 vendor/github.com/gaissmai/bart/node.go create mode 100644 vendor/github.com/gaissmai/bart/stringify.go create mode 100644 vendor/github.com/gaissmai/bart/table.go create mode 100644 vendor/github.com/go-json-experiment/json/AUTHORS create mode 100644 vendor/github.com/go-json-experiment/json/CONTRIBUTORS create mode 100644 vendor/github.com/go-json-experiment/json/LICENSE create mode 100644 vendor/github.com/go-json-experiment/json/README.md create mode 100644 vendor/github.com/go-json-experiment/json/api.png create mode 100644 vendor/github.com/go-json-experiment/json/arshal.go create mode 100644 vendor/github.com/go-json-experiment/json/arshal_any.go create mode 100644 vendor/github.com/go-json-experiment/json/arshal_default.go create mode 100644 vendor/github.com/go-json-experiment/json/arshal_funcs.go create mode 100644 vendor/github.com/go-json-experiment/json/arshal_inlined.go create mode 100644 vendor/github.com/go-json-experiment/json/arshal_methods.go create mode 100644 vendor/github.com/go-json-experiment/json/arshal_time.go create mode 100644 vendor/github.com/go-json-experiment/json/benchmark-marshal-concrete.png create mode 100644 vendor/github.com/go-json-experiment/json/benchmark-marshal-interface.png create mode 100644 vendor/github.com/go-json-experiment/json/benchmark-marshal-rawvalue.png create mode 100644 vendor/github.com/go-json-experiment/json/benchmark-unmarshal-concrete.png create mode 100644 vendor/github.com/go-json-experiment/json/benchmark-unmarshal-interface.png create mode 100644 vendor/github.com/go-json-experiment/json/benchmark-unmarshal-rawvalue.png create mode 100644 vendor/github.com/go-json-experiment/json/doc.go create mode 100644 vendor/github.com/go-json-experiment/json/errors.go create mode 100644 vendor/github.com/go-json-experiment/json/fields.go create mode 100644 vendor/github.com/go-json-experiment/json/fold.go create mode 100644 vendor/github.com/go-json-experiment/json/intern.go create mode 100644 vendor/github.com/go-json-experiment/json/internal/internal.go create mode 100644 vendor/github.com/go-json-experiment/json/internal/jsonflags/flags.go create mode 100644 vendor/github.com/go-json-experiment/json/internal/jsonopts/options.go create mode 100644 vendor/github.com/go-json-experiment/json/internal/jsonwire/decode.go create mode 100644 vendor/github.com/go-json-experiment/json/internal/jsonwire/encode.go create mode 100644 vendor/github.com/go-json-experiment/json/internal/jsonwire/wire.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/decode.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/doc.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/encode.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/errors.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/export.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/options.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/pools.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/quote.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/state.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/token.go create mode 100644 vendor/github.com/go-json-experiment/json/jsontext/value.go create mode 100644 vendor/github.com/go-json-experiment/json/options.go create mode 100644 vendor/github.com/godbus/dbus/v5/.cirrus.yml create mode 100644 vendor/github.com/godbus/dbus/v5/.golangci.yml create mode 100644 vendor/github.com/godbus/dbus/v5/CONTRIBUTING.md create mode 100644 vendor/github.com/godbus/dbus/v5/LICENSE create mode 100644 vendor/github.com/godbus/dbus/v5/MAINTAINERS create mode 100644 vendor/github.com/godbus/dbus/v5/README.md create mode 100644 vendor/github.com/godbus/dbus/v5/SECURITY.md create mode 100644 vendor/github.com/godbus/dbus/v5/auth.go create mode 100644 vendor/github.com/godbus/dbus/v5/auth_anonymous.go create mode 100644 vendor/github.com/godbus/dbus/v5/auth_external.go create mode 100644 vendor/github.com/godbus/dbus/v5/auth_sha1.go create mode 100644 vendor/github.com/godbus/dbus/v5/call.go create mode 100644 vendor/github.com/godbus/dbus/v5/conn.go create mode 100644 vendor/github.com/godbus/dbus/v5/conn_darwin.go create mode 100644 vendor/github.com/godbus/dbus/v5/conn_other.go create mode 100644 vendor/github.com/godbus/dbus/v5/conn_unix.go create mode 100644 vendor/github.com/godbus/dbus/v5/conn_windows.go create mode 100644 vendor/github.com/godbus/dbus/v5/dbus.go create mode 100644 vendor/github.com/godbus/dbus/v5/decoder.go create mode 100644 vendor/github.com/godbus/dbus/v5/default_handler.go create mode 100644 vendor/github.com/godbus/dbus/v5/doc.go create mode 100644 vendor/github.com/godbus/dbus/v5/encoder.go create mode 100644 vendor/github.com/godbus/dbus/v5/escape.go create mode 100644 vendor/github.com/godbus/dbus/v5/export.go create mode 100644 vendor/github.com/godbus/dbus/v5/homedir.go create mode 100644 vendor/github.com/godbus/dbus/v5/match.go create mode 100644 vendor/github.com/godbus/dbus/v5/message.go create mode 100644 vendor/github.com/godbus/dbus/v5/object.go create mode 100644 vendor/github.com/godbus/dbus/v5/sequence.go create mode 100644 vendor/github.com/godbus/dbus/v5/sequential_handler.go create mode 100644 vendor/github.com/godbus/dbus/v5/server_interfaces.go create mode 100644 vendor/github.com/godbus/dbus/v5/sig.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_darwin.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_generic.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_nonce_tcp.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_tcp.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_unix.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_dragonfly.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_freebsd.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_linux.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_netbsd.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_unixcred_openbsd.go create mode 100644 vendor/github.com/godbus/dbus/v5/transport_zos.go create mode 100644 vendor/github.com/godbus/dbus/v5/variant.go create mode 100644 vendor/github.com/godbus/dbus/v5/variant_lexer.go create mode 100644 vendor/github.com/godbus/dbus/v5/variant_parser.go create mode 100644 vendor/github.com/google/gnostic-models/openapiv3/annotations.pb.go create mode 100644 vendor/github.com/google/gnostic-models/openapiv3/annotations.proto create mode 100644 vendor/github.com/google/nftables/CONTRIBUTING.md rename vendor/{tags.cncf.io/container-device-interface => github.com/google/nftables}/LICENSE (99%) create mode 100644 vendor/github.com/google/nftables/README.md create mode 100644 vendor/github.com/google/nftables/alignedbuff/alignedbuff.go create mode 100644 vendor/github.com/google/nftables/binaryutil/binaryutil.go create mode 100644 vendor/github.com/google/nftables/chain.go create mode 100644 vendor/github.com/google/nftables/compat_policy.go create mode 100644 vendor/github.com/google/nftables/conn.go create mode 100644 vendor/github.com/google/nftables/counter.go create mode 100644 vendor/github.com/google/nftables/doc.go create mode 100644 vendor/github.com/google/nftables/expr/bitwise.go create mode 100644 vendor/github.com/google/nftables/expr/byteorder.go create mode 100644 vendor/github.com/google/nftables/expr/connlimit.go create mode 100644 vendor/github.com/google/nftables/expr/counter.go create mode 100644 vendor/github.com/google/nftables/expr/ct.go create mode 100644 vendor/github.com/google/nftables/expr/dup.go create mode 100644 vendor/github.com/google/nftables/expr/dynset.go create mode 100644 vendor/github.com/google/nftables/expr/expr.go create mode 100644 vendor/github.com/google/nftables/expr/exthdr.go create mode 100644 vendor/github.com/google/nftables/expr/fib.go create mode 100644 vendor/github.com/google/nftables/expr/flow_offload.go create mode 100644 vendor/github.com/google/nftables/expr/hash.go create mode 100644 vendor/github.com/google/nftables/expr/immediate.go create mode 100644 vendor/github.com/google/nftables/expr/limit.go create mode 100644 vendor/github.com/google/nftables/expr/log.go create mode 100644 vendor/github.com/google/nftables/expr/lookup.go create mode 100644 vendor/github.com/google/nftables/expr/match.go create mode 100644 vendor/github.com/google/nftables/expr/nat.go rename vendor/{gvisor.dev/gvisor/pkg/sync/runtime_exectracer1.go => github.com/google/nftables/expr/notrack.go} (50%) create mode 100644 vendor/github.com/google/nftables/expr/numgen.go create mode 100644 vendor/github.com/google/nftables/expr/objref.go create mode 100644 vendor/github.com/google/nftables/expr/payload.go create mode 100644 vendor/github.com/google/nftables/expr/queue.go create mode 100644 vendor/github.com/google/nftables/expr/quota.go create mode 100644 vendor/github.com/google/nftables/expr/range.go create mode 100644 vendor/github.com/google/nftables/expr/redirect.go create mode 100644 vendor/github.com/google/nftables/expr/reject.go create mode 100644 vendor/github.com/google/nftables/expr/rt.go create mode 100644 vendor/github.com/google/nftables/expr/socket.go create mode 100644 vendor/github.com/google/nftables/expr/target.go create mode 100644 vendor/github.com/google/nftables/expr/tproxy.go create mode 100644 vendor/github.com/google/nftables/expr/verdict.go create mode 100644 vendor/github.com/google/nftables/flowtable.go create mode 100644 vendor/github.com/google/nftables/internal/parseexprfunc/parseexprfunc.go create mode 100644 vendor/github.com/google/nftables/monitor.go create mode 100644 vendor/github.com/google/nftables/obj.go create mode 100644 vendor/github.com/google/nftables/quota.go create mode 100644 vendor/github.com/google/nftables/rule.go create mode 100644 vendor/github.com/google/nftables/set.go create mode 100644 vendor/github.com/google/nftables/table.go create mode 100644 vendor/github.com/google/nftables/util.go create mode 100644 vendor/github.com/google/nftables/xt/info.go create mode 100644 vendor/github.com/google/nftables/xt/match_addrtype.go create mode 100644 vendor/github.com/google/nftables/xt/match_conntrack.go create mode 100644 vendor/github.com/google/nftables/xt/match_tcp.go create mode 100644 vendor/github.com/google/nftables/xt/match_udp.go create mode 100644 vendor/github.com/google/nftables/xt/target_dnat.go create mode 100644 vendor/github.com/google/nftables/xt/target_masquerade_ip.go create mode 100644 vendor/github.com/google/nftables/xt/unknown.go create mode 100644 vendor/github.com/google/nftables/xt/util.go create mode 100644 vendor/github.com/google/nftables/xt/xt.go create mode 100644 vendor/github.com/hdevalence/ed25519consensus/LICENSE create mode 100644 vendor/github.com/hdevalence/ed25519consensus/README.md create mode 100644 vendor/github.com/hdevalence/ed25519consensus/batch.go create mode 100644 vendor/github.com/hdevalence/ed25519consensus/ed25519.go create mode 100644 vendor/github.com/illarion/gonotify/.gitignore create mode 100644 vendor/github.com/illarion/gonotify/.travis.yml create mode 100644 vendor/github.com/illarion/gonotify/LICENSE create mode 100644 vendor/github.com/illarion/gonotify/README.md create mode 100644 vendor/github.com/illarion/gonotify/dirwatcher.go create mode 100644 vendor/github.com/illarion/gonotify/event.go create mode 100644 vendor/github.com/illarion/gonotify/filewatcher.go create mode 100644 vendor/github.com/illarion/gonotify/inotify.go create mode 100644 vendor/github.com/josharian/native/doc.go create mode 100644 vendor/github.com/josharian/native/endian_generic.go create mode 100644 vendor/github.com/josharian/native/license create mode 100644 vendor/github.com/josharian/native/readme.md create mode 100644 vendor/github.com/jsimonetti/rtnetlink/.gitignore create mode 100644 vendor/github.com/jsimonetti/rtnetlink/LICENSE.md create mode 100644 vendor/github.com/jsimonetti/rtnetlink/Makefile.fuzz create mode 100644 vendor/github.com/jsimonetti/rtnetlink/README.md create mode 100644 vendor/github.com/jsimonetti/rtnetlink/address.go create mode 100644 vendor/github.com/jsimonetti/rtnetlink/conn.go create mode 100644 vendor/github.com/jsimonetti/rtnetlink/doc.go create mode 100644 vendor/github.com/jsimonetti/rtnetlink/endian.go create mode 100644 vendor/github.com/jsimonetti/rtnetlink/fuzz-shell.nix create mode 100644 vendor/github.com/jsimonetti/rtnetlink/internal/unix/types_linux.go create mode 100644 vendor/github.com/jsimonetti/rtnetlink/internal/unix/types_other.go create mode 100644 vendor/github.com/jsimonetti/rtnetlink/link.go create mode 100644 vendor/github.com/jsimonetti/rtnetlink/neigh.go create mode 100644 vendor/github.com/jsimonetti/rtnetlink/route.go create mode 100644 vendor/github.com/jsimonetti/rtnetlink/rule.go create mode 100644 vendor/github.com/mdlayher/netlink/.gitignore create mode 100644 vendor/github.com/mdlayher/netlink/CHANGELOG.md create mode 100644 vendor/github.com/mdlayher/netlink/LICENSE.md create mode 100644 vendor/github.com/mdlayher/netlink/README.md create mode 100644 vendor/github.com/mdlayher/netlink/align.go create mode 100644 vendor/github.com/mdlayher/netlink/attribute.go create mode 100644 vendor/github.com/mdlayher/netlink/conn.go create mode 100644 vendor/github.com/mdlayher/netlink/conn_linux.go create mode 100644 vendor/github.com/mdlayher/netlink/conn_others.go create mode 100644 vendor/github.com/mdlayher/netlink/debug.go create mode 100644 vendor/github.com/mdlayher/netlink/doc.go create mode 100644 vendor/github.com/mdlayher/netlink/errors.go create mode 100644 vendor/github.com/mdlayher/netlink/fuzz.go create mode 100644 vendor/github.com/mdlayher/netlink/message.go create mode 100644 vendor/github.com/mdlayher/netlink/nlenc/doc.go create mode 100644 vendor/github.com/mdlayher/netlink/nlenc/int.go create mode 100644 vendor/github.com/mdlayher/netlink/nlenc/string.go create mode 100644 vendor/github.com/mdlayher/netlink/nltest/errors_others.go create mode 100644 vendor/github.com/mdlayher/netlink/nltest/errors_unix.go create mode 100644 vendor/github.com/mdlayher/netlink/nltest/nltest.go create mode 100644 vendor/github.com/mdlayher/socket/CHANGELOG.md create mode 100644 vendor/github.com/mdlayher/socket/LICENSE.md create mode 100644 vendor/github.com/mdlayher/socket/README.md create mode 100644 vendor/github.com/mdlayher/socket/accept.go create mode 100644 vendor/github.com/mdlayher/socket/accept4.go create mode 100644 vendor/github.com/mdlayher/socket/conn.go create mode 100644 vendor/github.com/mdlayher/socket/conn_linux.go create mode 100644 vendor/github.com/mdlayher/socket/doc.go create mode 100644 vendor/github.com/mdlayher/socket/netns_linux.go create mode 100644 vendor/github.com/mdlayher/socket/netns_others.go create mode 100644 vendor/github.com/mdlayher/socket/setbuffer_linux.go create mode 100644 vendor/github.com/mdlayher/socket/setbuffer_others.go create mode 100644 vendor/github.com/mdlayher/socket/typ_cloexec_nonblock.go create mode 100644 vendor/github.com/mdlayher/socket/typ_none.go create mode 100644 vendor/github.com/tailscale/netlink/.gitignore create mode 100644 vendor/github.com/tailscale/netlink/.travis.yml create mode 100644 vendor/github.com/tailscale/netlink/CHANGELOG.md create mode 100644 vendor/github.com/tailscale/netlink/LICENSE create mode 100644 vendor/github.com/tailscale/netlink/Makefile create mode 100644 vendor/github.com/tailscale/netlink/README.md create mode 100644 vendor/github.com/tailscale/netlink/addr.go create mode 100644 vendor/github.com/tailscale/netlink/addr_linux.go create mode 100644 vendor/github.com/tailscale/netlink/bpf_linux.go create mode 100644 vendor/github.com/tailscale/netlink/bridge_linux.go create mode 100644 vendor/github.com/tailscale/netlink/class.go create mode 100644 vendor/github.com/tailscale/netlink/class_linux.go create mode 100644 vendor/github.com/tailscale/netlink/conntrack_linux.go create mode 100644 vendor/github.com/tailscale/netlink/conntrack_unspecified.go create mode 100644 vendor/github.com/tailscale/netlink/devlink_linux.go create mode 100644 vendor/github.com/tailscale/netlink/filter.go create mode 100644 vendor/github.com/tailscale/netlink/filter_linux.go create mode 100644 vendor/github.com/tailscale/netlink/fou.go create mode 100644 vendor/github.com/tailscale/netlink/fou_linux.go create mode 100644 vendor/github.com/tailscale/netlink/fou_unspecified.go create mode 100644 vendor/github.com/tailscale/netlink/genetlink_linux.go create mode 100644 vendor/github.com/tailscale/netlink/genetlink_unspecified.go create mode 100644 vendor/github.com/tailscale/netlink/gtp_linux.go create mode 100644 vendor/github.com/tailscale/netlink/handle_linux.go create mode 100644 vendor/github.com/tailscale/netlink/handle_unspecified.go create mode 100644 vendor/github.com/tailscale/netlink/inet_diag.go create mode 100644 vendor/github.com/tailscale/netlink/ioctl_linux.go create mode 100644 vendor/github.com/tailscale/netlink/ipset_linux.go create mode 100644 vendor/github.com/tailscale/netlink/link.go create mode 100644 vendor/github.com/tailscale/netlink/link_linux.go create mode 100644 vendor/github.com/tailscale/netlink/link_tuntap_linux.go create mode 100644 vendor/github.com/tailscale/netlink/neigh.go create mode 100644 vendor/github.com/tailscale/netlink/neigh_linux.go create mode 100644 vendor/github.com/tailscale/netlink/netlink.go create mode 100644 vendor/github.com/tailscale/netlink/netlink_linux.go create mode 100644 vendor/github.com/tailscale/netlink/netlink_unspecified.go create mode 100644 vendor/github.com/tailscale/netlink/netns_linux.go create mode 100644 vendor/github.com/tailscale/netlink/netns_unspecified.go create mode 100644 vendor/github.com/tailscale/netlink/order.go create mode 100644 vendor/github.com/tailscale/netlink/protinfo.go create mode 100644 vendor/github.com/tailscale/netlink/protinfo_linux.go create mode 100644 vendor/github.com/tailscale/netlink/qdisc.go create mode 100644 vendor/github.com/tailscale/netlink/qdisc_linux.go create mode 100644 vendor/github.com/tailscale/netlink/rdma_link_linux.go create mode 100644 vendor/github.com/tailscale/netlink/route.go create mode 100644 vendor/github.com/tailscale/netlink/route_linux.go create mode 100644 vendor/github.com/tailscale/netlink/route_unspecified.go create mode 100644 vendor/github.com/tailscale/netlink/rule.go create mode 100644 vendor/github.com/tailscale/netlink/rule_linux.go create mode 100644 vendor/github.com/tailscale/netlink/socket.go create mode 100644 vendor/github.com/tailscale/netlink/socket_linux.go create mode 100644 vendor/github.com/tailscale/netlink/tcp.go create mode 100644 vendor/github.com/tailscale/netlink/tcp_linux.go create mode 100644 vendor/github.com/tailscale/netlink/xfrm.go create mode 100644 vendor/github.com/tailscale/netlink/xfrm_monitor_linux.go create mode 100644 vendor/github.com/tailscale/netlink/xfrm_policy.go create mode 100644 vendor/github.com/tailscale/netlink/xfrm_policy_linux.go create mode 100644 vendor/github.com/tailscale/netlink/xfrm_state.go create mode 100644 vendor/github.com/tailscale/netlink/xfrm_state_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/LICENSE create mode 100644 vendor/github.com/vishvananda/netlink/nl/addr_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/bridge_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/conntrack_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/devlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/genetlink_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/ipset_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/lwt_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/mpls_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/nl_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/nl_unspecified.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/parse_attr_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/rdma_link_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/route_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/seg6_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/seg6local_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/syscall.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/tc_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_monitor_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_policy_linux.go create mode 100644 vendor/github.com/vishvananda/netlink/nl/xfrm_state_linux.go create mode 100644 vendor/github.com/vishvananda/netns/.golangci.yml create mode 100644 vendor/github.com/vishvananda/netns/LICENSE create mode 100644 vendor/github.com/vishvananda/netns/README.md create mode 100644 vendor/github.com/vishvananda/netns/doc.go create mode 100644 vendor/github.com/vishvananda/netns/netns_linux.go create mode 100644 vendor/github.com/vishvananda/netns/netns_others.go create mode 100644 vendor/github.com/vishvananda/netns/nshandle_linux.go create mode 100644 vendor/github.com/vishvananda/netns/nshandle_others.go create mode 100644 vendor/github.com/x448/float16/.travis.yml create mode 100644 vendor/github.com/x448/float16/LICENSE create mode 100644 vendor/github.com/x448/float16/README.md create mode 100644 vendor/github.com/x448/float16/float16.go create mode 100644 vendor/go4.org/mem/LICENSE create mode 100644 vendor/go4.org/mem/README.md create mode 100644 vendor/go4.org/mem/fields.go create mode 100644 vendor/go4.org/mem/fold.go create mode 100644 vendor/go4.org/mem/mem.go create mode 100644 vendor/go4.org/netipx/.gitignore create mode 100644 vendor/go4.org/netipx/.gitmodules create mode 100644 vendor/go4.org/netipx/AUTHORS create mode 100644 vendor/go4.org/netipx/LICENSE create mode 100644 vendor/go4.org/netipx/README.md create mode 100644 vendor/go4.org/netipx/ipset.go create mode 100644 vendor/go4.org/netipx/mask6.go create mode 100644 vendor/go4.org/netipx/netipx.go create mode 100644 vendor/go4.org/netipx/uint128.go create mode 100644 vendor/golang.org/x/crypto/argon2/argon2.go create mode 100644 vendor/golang.org/x/crypto/argon2/blake2b.go create mode 100644 vendor/golang.org/x/crypto/argon2/blamka_amd64.go create mode 100644 vendor/golang.org/x/crypto/argon2/blamka_amd64.s create mode 100644 vendor/golang.org/x/crypto/argon2/blamka_generic.go create mode 100644 vendor/golang.org/x/crypto/argon2/blamka_ref.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2bAVX2_amd64.s create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_amd64.s create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_generic.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2b_ref.go create mode 100644 vendor/golang.org/x/crypto/blake2b/blake2x.go create mode 100644 vendor/golang.org/x/crypto/blake2b/register.go delete mode 100644 vendor/golang.org/x/crypto/blake2s/register.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_compat.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/curve25519_go120.go delete mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/README delete mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/sync.checkpoint delete mode 100644 vendor/golang.org/x/crypto/curve25519/internal/field/sync.sh create mode 100644 vendor/golang.org/x/crypto/nacl/box/box.go create mode 100644 vendor/golang.org/x/crypto/nacl/secretbox/secretbox.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/hsalsa20.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa208.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.s create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_noasm.go create mode 100644 vendor/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go create mode 100644 vendor/golang.org/x/net/dns/dnsmessage/message.go create mode 100644 vendor/golang.org/x/net/http/httpproxy/proxy.go delete mode 100644 vendor/golang.org/x/net/http2/testsync.go create mode 100644 vendor/golang.org/x/net/http2/timer.go create mode 100644 vendor/golang.org/x/sys/windows/svc/mgr/config.go create mode 100644 vendor/golang.org/x/sys/windows/svc/mgr/mgr.go create mode 100644 vendor/golang.org/x/sys/windows/svc/mgr/recovery.go create mode 100644 vendor/golang.org/x/sys/windows/svc/mgr/service.go create mode 100644 vendor/golang.org/x/sys/windows/svc/security.go create mode 100644 vendor/golang.org/x/sys/windows/svc/service.go delete mode 100644 vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go rename vendor/gvisor.dev/gvisor/pkg/goid/{goid_amd64.s => goid_122_amd64.s} (97%) rename vendor/gvisor.dev/gvisor/pkg/goid/{goid_arm64.s => goid_122_arm64.s} (97%) create mode 100644 vendor/gvisor.dev/gvisor/pkg/goid/goid_123_amd64.s create mode 100644 vendor/gvisor.dev/gvisor/pkg/goid/goid_123_arm64.s create mode 100644 vendor/gvisor.dev/gvisor/pkg/tcpip/errors_linux.go rename vendor/gvisor.dev/gvisor/pkg/tcpip/{stack/gro_packet_list.go => route_list.go} (61%) create mode 100644 vendor/gvisor.dev/gvisor/pkg/tcpip/stack/bridge.go create mode 100644 vendor/gvisor.dev/gvisor/pkg/tcpip/stack/bridge_mutex.go delete mode 100644 vendor/gvisor.dev/gvisor/pkg/tcpip/stack/gro.go create mode 100644 vendor/gvisor.dev/gvisor/pkg/tcpip/tcpip_linux_state_autogen.go delete mode 100644 vendor/k8s.io/component-base/config/OWNERS delete mode 100644 vendor/k8s.io/component-base/config/doc.go delete mode 100644 vendor/k8s.io/component-base/config/types.go delete mode 100644 vendor/k8s.io/component-base/config/v1alpha1/conversion.go delete mode 100644 vendor/k8s.io/component-base/config/v1alpha1/defaults.go delete mode 100644 vendor/k8s.io/component-base/config/v1alpha1/doc.go delete mode 100644 vendor/k8s.io/component-base/config/v1alpha1/register.go delete mode 100644 vendor/k8s.io/component-base/config/v1alpha1/types.go delete mode 100644 vendor/k8s.io/component-base/config/v1alpha1/zz_generated.conversion.go delete mode 100644 vendor/k8s.io/component-base/config/v1alpha1/zz_generated.deepcopy.go delete mode 100644 vendor/k8s.io/component-base/config/zz_generated.deepcopy.go create mode 100644 vendor/k8s.io/utils/net/multi_listen.go create mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/client/fieldowner.go delete mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/config/config.go delete mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/config/doc.go delete mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1/doc.go delete mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1/register.go delete mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1/types.go delete mode 100644 vendor/sigs.k8s.io/controller-runtime/pkg/config/v1alpha1/zz_generated.deepcopy.go delete mode 100644 vendor/tags.cncf.io/container-device-interface/pkg/parser/parser.go create mode 100644 vendor/tailscale.com/.gitattributes create mode 100644 vendor/tailscale.com/.gitignore create mode 100644 vendor/tailscale.com/.golangci.yml create mode 100644 vendor/tailscale.com/ALPINE.txt create mode 100644 vendor/tailscale.com/AUTHORS create mode 100644 vendor/tailscale.com/CODEOWNERS create mode 100644 vendor/tailscale.com/CODE_OF_CONDUCT.md create mode 100644 vendor/tailscale.com/Dockerfile create mode 100644 vendor/tailscale.com/Dockerfile.base create mode 100644 vendor/tailscale.com/LICENSE create mode 100644 vendor/tailscale.com/Makefile create mode 100644 vendor/tailscale.com/PATENTS create mode 100644 vendor/tailscale.com/README.md create mode 100644 vendor/tailscale.com/SECURITY.md create mode 100644 vendor/tailscale.com/VERSION.txt create mode 100644 vendor/tailscale.com/api.md create mode 100644 vendor/tailscale.com/atomicfile/atomicfile.go create mode 100644 vendor/tailscale.com/build_dist.sh create mode 100644 vendor/tailscale.com/build_docker.sh create mode 100644 vendor/tailscale.com/control/controlknobs/controlknobs.go create mode 100644 vendor/tailscale.com/envknob/envknob.go create mode 100644 vendor/tailscale.com/envknob/envknob_nottest.go create mode 100644 vendor/tailscale.com/envknob/envknob_testable.go create mode 100644 vendor/tailscale.com/envknob/features.go create mode 100644 vendor/tailscale.com/flake.lock create mode 100644 vendor/tailscale.com/flake.nix create mode 100644 vendor/tailscale.com/go.mod.sri create mode 100644 vendor/tailscale.com/go.toolchain.branch create mode 100644 vendor/tailscale.com/go.toolchain.rev create mode 100644 vendor/tailscale.com/header.txt create mode 100644 vendor/tailscale.com/health/args.go create mode 100644 vendor/tailscale.com/health/health.go create mode 100644 vendor/tailscale.com/health/state.go create mode 100644 vendor/tailscale.com/health/warnings.go create mode 100644 vendor/tailscale.com/hostinfo/hostinfo.go create mode 100644 vendor/tailscale.com/hostinfo/hostinfo_darwin.go create mode 100644 vendor/tailscale.com/hostinfo/hostinfo_freebsd.go create mode 100644 vendor/tailscale.com/hostinfo/hostinfo_linux.go create mode 100644 vendor/tailscale.com/hostinfo/hostinfo_uname.go create mode 100644 vendor/tailscale.com/hostinfo/hostinfo_windows.go create mode 100644 vendor/tailscale.com/hostinfo/packagetype_container.go create mode 100644 vendor/tailscale.com/hostinfo/wol.go create mode 100644 vendor/tailscale.com/logtail/backoff/backoff.go create mode 100644 vendor/tailscale.com/net/dns/config.go create mode 100644 vendor/tailscale.com/net/dns/debian_resolvconf.go create mode 100644 vendor/tailscale.com/net/dns/direct.go create mode 100644 vendor/tailscale.com/net/dns/direct_linux.go create mode 100644 vendor/tailscale.com/net/dns/direct_notlinux.go create mode 100644 vendor/tailscale.com/net/dns/flush_default.go create mode 100644 vendor/tailscale.com/net/dns/flush_windows.go create mode 100644 vendor/tailscale.com/net/dns/ini.go create mode 100644 vendor/tailscale.com/net/dns/manager.go create mode 100644 vendor/tailscale.com/net/dns/manager_darwin.go create mode 100644 vendor/tailscale.com/net/dns/manager_default.go create mode 100644 vendor/tailscale.com/net/dns/manager_freebsd.go create mode 100644 vendor/tailscale.com/net/dns/manager_linux.go create mode 100644 vendor/tailscale.com/net/dns/manager_openbsd.go create mode 100644 vendor/tailscale.com/net/dns/manager_windows.go create mode 100644 vendor/tailscale.com/net/dns/nm.go create mode 100644 vendor/tailscale.com/net/dns/noop.go create mode 100644 vendor/tailscale.com/net/dns/nrpt_windows.go create mode 100644 vendor/tailscale.com/net/dns/openresolv.go create mode 100644 vendor/tailscale.com/net/dns/osconfig.go create mode 100644 vendor/tailscale.com/net/dns/publicdns/publicdns.go create mode 100644 vendor/tailscale.com/net/dns/resolvconf-workaround.sh create mode 100644 vendor/tailscale.com/net/dns/resolvconf.go create mode 100644 vendor/tailscale.com/net/dns/resolvconffile/resolvconffile.go create mode 100644 vendor/tailscale.com/net/dns/resolvconfpath_default.go create mode 100644 vendor/tailscale.com/net/dns/resolvconfpath_gokrazy.go create mode 100644 vendor/tailscale.com/net/dns/resolvd.go create mode 100644 vendor/tailscale.com/net/dns/resolved.go create mode 100644 vendor/tailscale.com/net/dns/resolver/debug.go create mode 100644 vendor/tailscale.com/net/dns/resolver/forwarder.go create mode 100644 vendor/tailscale.com/net/dns/resolver/macios_ext.go create mode 100644 vendor/tailscale.com/net/dns/resolver/tsdns.go create mode 100644 vendor/tailscale.com/net/dns/utf.go create mode 100644 vendor/tailscale.com/net/dns/wsl_windows.go create mode 100644 vendor/tailscale.com/net/dnscache/dnscache.go create mode 100644 vendor/tailscale.com/net/dnscache/messagecache.go create mode 100644 vendor/tailscale.com/net/netaddr/netaddr.go create mode 100644 vendor/tailscale.com/net/neterror/neterror.go create mode 100644 vendor/tailscale.com/net/neterror/neterror_linux.go create mode 100644 vendor/tailscale.com/net/neterror/neterror_windows.go create mode 100644 vendor/tailscale.com/net/netknob/netknob.go create mode 100644 vendor/tailscale.com/net/netmon/defaultroute_bsd.go create mode 100644 vendor/tailscale.com/net/netmon/defaultroute_darwin.go create mode 100644 vendor/tailscale.com/net/netmon/interfaces_android.go create mode 100644 vendor/tailscale.com/net/netmon/interfaces_bsd.go create mode 100644 vendor/tailscale.com/net/netmon/interfaces_darwin.go create mode 100644 vendor/tailscale.com/net/netmon/interfaces_defaultrouteif_todo.go create mode 100644 vendor/tailscale.com/net/netmon/interfaces_freebsd.go create mode 100644 vendor/tailscale.com/net/netmon/interfaces_linux.go create mode 100644 vendor/tailscale.com/net/netmon/interfaces_windows.go create mode 100644 vendor/tailscale.com/net/netmon/netmon.go create mode 100644 vendor/tailscale.com/net/netmon/netmon_darwin.go create mode 100644 vendor/tailscale.com/net/netmon/netmon_freebsd.go create mode 100644 vendor/tailscale.com/net/netmon/netmon_linux.go create mode 100644 vendor/tailscale.com/net/netmon/netmon_polling.go create mode 100644 vendor/tailscale.com/net/netmon/netmon_windows.go create mode 100644 vendor/tailscale.com/net/netmon/polling.go create mode 100644 vendor/tailscale.com/net/netmon/state.go create mode 100644 vendor/tailscale.com/net/netns/mksyscall.go create mode 100644 vendor/tailscale.com/net/netns/netns.go create mode 100644 vendor/tailscale.com/net/netns/netns_android.go create mode 100644 vendor/tailscale.com/net/netns/netns_darwin.go create mode 100644 vendor/tailscale.com/net/netns/netns_default.go create mode 100644 vendor/tailscale.com/net/netns/netns_dw.go create mode 100644 vendor/tailscale.com/net/netns/netns_linux.go create mode 100644 vendor/tailscale.com/net/netns/netns_windows.go create mode 100644 vendor/tailscale.com/net/netns/socks.go create mode 100644 vendor/tailscale.com/net/netns/zsyscall_windows.go create mode 100644 vendor/tailscale.com/net/sockstats/label_string.go create mode 100644 vendor/tailscale.com/net/sockstats/sockstats.go create mode 100644 vendor/tailscale.com/net/sockstats/sockstats_noop.go create mode 100644 vendor/tailscale.com/net/sockstats/sockstats_tsgo.go create mode 100644 vendor/tailscale.com/net/sockstats/sockstats_tsgo_darwin.go create mode 100644 vendor/tailscale.com/net/tsaddr/tsaddr.go create mode 100644 vendor/tailscale.com/net/tsdial/dnsmap.go create mode 100644 vendor/tailscale.com/net/tsdial/dohclient.go create mode 100644 vendor/tailscale.com/net/tsdial/peerapi_macios_ext.go create mode 100644 vendor/tailscale.com/net/tsdial/tsdial.go create mode 100644 vendor/tailscale.com/net/tshttpproxy/mksyscall.go create mode 100644 vendor/tailscale.com/net/tshttpproxy/tshttpproxy.go create mode 100644 vendor/tailscale.com/net/tshttpproxy/tshttpproxy_linux.go create mode 100644 vendor/tailscale.com/net/tshttpproxy/tshttpproxy_synology.go create mode 100644 vendor/tailscale.com/net/tshttpproxy/tshttpproxy_windows.go create mode 100644 vendor/tailscale.com/net/tshttpproxy/zsyscall_windows.go create mode 100644 vendor/tailscale.com/pull-toolchain.sh create mode 100644 vendor/tailscale.com/shell.nix create mode 100644 vendor/tailscale.com/staticcheck.conf create mode 100644 vendor/tailscale.com/syncs/locked.go create mode 100644 vendor/tailscale.com/syncs/pool.go create mode 100644 vendor/tailscale.com/syncs/shardedmap.go create mode 100644 vendor/tailscale.com/syncs/syncs.go create mode 100644 vendor/tailscale.com/tailcfg/c2ntypes.go create mode 100644 vendor/tailscale.com/tailcfg/derpmap.go create mode 100644 vendor/tailscale.com/tailcfg/proto_port_range.go create mode 100644 vendor/tailscale.com/tailcfg/tailcfg.go create mode 100644 vendor/tailscale.com/tailcfg/tailcfg_clone.go create mode 100644 vendor/tailscale.com/tailcfg/tailcfg_view.go create mode 100644 vendor/tailscale.com/tailcfg/tka.go create mode 100644 vendor/tailscale.com/tka/aum.go create mode 100644 vendor/tailscale.com/tka/builder.go create mode 100644 vendor/tailscale.com/tka/deeplink.go create mode 100644 vendor/tailscale.com/tka/key.go create mode 100644 vendor/tailscale.com/tka/sig.go create mode 100644 vendor/tailscale.com/tka/state.go create mode 100644 vendor/tailscale.com/tka/sync.go create mode 100644 vendor/tailscale.com/tka/tailchonk.go create mode 100644 vendor/tailscale.com/tka/tka.go create mode 100644 vendor/tailscale.com/tsconst/interface.go create mode 100644 vendor/tailscale.com/tstime/jitter.go create mode 100644 vendor/tailscale.com/tstime/mono/mono.go create mode 100644 vendor/tailscale.com/tstime/rate/rate.go create mode 100644 vendor/tailscale.com/tstime/rate/value.go create mode 100644 vendor/tailscale.com/tstime/tstime.go create mode 100644 vendor/tailscale.com/types/dnstype/dnstype.go create mode 100644 vendor/tailscale.com/types/dnstype/dnstype_clone.go create mode 100644 vendor/tailscale.com/types/dnstype/dnstype_view.go create mode 100644 vendor/tailscale.com/types/ipproto/ipproto.go create mode 100644 vendor/tailscale.com/types/key/chal.go create mode 100644 vendor/tailscale.com/types/key/control.go create mode 100644 vendor/tailscale.com/types/key/disco.go create mode 100644 vendor/tailscale.com/types/key/doc.go create mode 100644 vendor/tailscale.com/types/key/machine.go create mode 100644 vendor/tailscale.com/types/key/nl.go create mode 100644 vendor/tailscale.com/types/key/node.go create mode 100644 vendor/tailscale.com/types/key/util.go create mode 100644 vendor/tailscale.com/types/lazy/lazy.go create mode 100644 vendor/tailscale.com/types/lazy/unsync.go create mode 100644 vendor/tailscale.com/types/logger/logger.go create mode 100644 vendor/tailscale.com/types/logger/rusage.go create mode 100644 vendor/tailscale.com/types/logger/rusage_stub.go create mode 100644 vendor/tailscale.com/types/logger/rusage_syscall.go create mode 100644 vendor/tailscale.com/types/logger/tokenbucket.go create mode 100644 vendor/tailscale.com/types/netmap/netmap.go create mode 100644 vendor/tailscale.com/types/netmap/nodemut.go create mode 100644 vendor/tailscale.com/types/nettype/nettype.go create mode 100644 vendor/tailscale.com/types/opt/bool.go create mode 100644 vendor/tailscale.com/types/opt/value.go create mode 100644 vendor/tailscale.com/types/ptr/ptr.go create mode 100644 vendor/tailscale.com/types/structs/structs.go create mode 100644 vendor/tailscale.com/types/tkatype/tkatype.go create mode 100644 vendor/tailscale.com/types/views/views.go create mode 100644 vendor/tailscale.com/update-flake.sh create mode 100644 vendor/tailscale.com/util/cibuild/cibuild.go create mode 100644 vendor/tailscale.com/util/clientmetric/clientmetric.go create mode 100644 vendor/tailscale.com/util/cloudenv/cloudenv.go create mode 100644 vendor/tailscale.com/util/cmpver/version.go create mode 100644 vendor/tailscale.com/util/ctxkey/key.go create mode 100644 vendor/tailscale.com/util/dnsname/dnsname.go create mode 100644 vendor/tailscale.com/util/lineread/lineread.go create mode 100644 vendor/tailscale.com/util/linuxfw/detector.go create mode 100644 vendor/tailscale.com/util/linuxfw/fake.go create mode 100644 vendor/tailscale.com/util/linuxfw/helpers.go create mode 100644 vendor/tailscale.com/util/linuxfw/iptables.go create mode 100644 vendor/tailscale.com/util/linuxfw/iptables_runner.go create mode 100644 vendor/tailscale.com/util/linuxfw/linuxfw.go create mode 100644 vendor/tailscale.com/util/linuxfw/linuxfw_unsupported.go create mode 100644 vendor/tailscale.com/util/linuxfw/nftables.go create mode 100644 vendor/tailscale.com/util/linuxfw/nftables_runner.go create mode 100644 vendor/tailscale.com/util/linuxfw/nftables_types.go create mode 100644 vendor/tailscale.com/util/mak/mak.go create mode 100644 vendor/tailscale.com/util/multierr/multierr.go create mode 100644 vendor/tailscale.com/util/nocasemaps/nocase.go create mode 100644 vendor/tailscale.com/util/race/race.go create mode 100644 vendor/tailscale.com/util/set/handle.go create mode 100644 vendor/tailscale.com/util/set/set.go create mode 100644 vendor/tailscale.com/util/set/slice.go create mode 100644 vendor/tailscale.com/util/singleflight/singleflight.go create mode 100644 vendor/tailscale.com/util/slicesx/slicesx.go create mode 100644 vendor/tailscale.com/util/testenv/testenv.go create mode 100644 vendor/tailscale.com/util/vizerror/vizerror.go create mode 100644 vendor/tailscale.com/util/winutil/gp/gp_windows.go create mode 100644 vendor/tailscale.com/util/winutil/gp/mksyscall.go create mode 100644 vendor/tailscale.com/util/winutil/gp/policylock_windows.go create mode 100644 vendor/tailscale.com/util/winutil/gp/watcher_windows.go create mode 100644 vendor/tailscale.com/util/winutil/gp/zsyscall_windows.go create mode 100644 vendor/tailscale.com/util/winutil/mksyscall.go create mode 100644 vendor/tailscale.com/util/winutil/restartmgr_windows.go create mode 100644 vendor/tailscale.com/util/winutil/startupinfo_windows.go create mode 100644 vendor/tailscale.com/util/winutil/svcdiag_windows.go create mode 100644 vendor/tailscale.com/util/winutil/userprofile_windows.go create mode 100644 vendor/tailscale.com/util/winutil/winenv/mksyscall.go create mode 100644 vendor/tailscale.com/util/winutil/winenv/winenv_windows.go create mode 100644 vendor/tailscale.com/util/winutil/winenv/zsyscall_windows.go create mode 100644 vendor/tailscale.com/util/winutil/winutil.go create mode 100644 vendor/tailscale.com/util/winutil/winutil_notwindows.go create mode 100644 vendor/tailscale.com/util/winutil/winutil_windows.go create mode 100644 vendor/tailscale.com/util/winutil/zsyscall_windows.go create mode 100644 vendor/tailscale.com/version-embed.go create mode 100644 vendor/tailscale.com/version/.gitignore create mode 100644 vendor/tailscale.com/version/cmdname.go create mode 100644 vendor/tailscale.com/version/cmdname_ios.go create mode 100644 vendor/tailscale.com/version/cmp.go create mode 100644 vendor/tailscale.com/version/distro/distro.go create mode 100644 vendor/tailscale.com/version/print.go create mode 100644 vendor/tailscale.com/version/prop.go create mode 100644 vendor/tailscale.com/version/race.go create mode 100644 vendor/tailscale.com/version/race_off.go create mode 100644 vendor/tailscale.com/version/version.go create mode 100644 vendor/tailscale.com/wgengine/filter/filtertype/filtertype.go create mode 100644 vendor/tailscale.com/wgengine/filter/filtertype/filtertype_clone.go diff --git a/go.mod b/go.mod index 968c7924..428af0e9 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/coredns/coredns v1.11.2 github.com/distribution/reference v0.6.0 github.com/docker/cli v26.0.0+incompatible - github.com/docker/docker v26.0.0+incompatible + github.com/docker/docker v26.1.4+incompatible github.com/docker/go-connections v0.5.0 github.com/docker/libcontainer v2.2.1+incompatible github.com/envoyproxy/go-control-plane v0.12.0 @@ -33,37 +33,36 @@ require ( github.com/prometheus-community/pro-bing v0.4.0 github.com/schollz/progressbar/v3 v3.14.2 github.com/sirupsen/logrus v1.9.3 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/syncthing/syncthing v1.27.7 github.com/thejerf/suture/v4 v4.0.5 go.uber.org/automaxprocs v1.5.3 - golang.org/x/crypto v0.23.0 - golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 - golang.org/x/net v0.25.0 + golang.org/x/crypto v0.25.0 + golang.org/x/net v0.27.0 golang.org/x/oauth2 v0.18.0 golang.org/x/sync v0.7.0 - golang.org/x/sys v0.20.0 - golang.org/x/text v0.15.0 + golang.org/x/sys v0.22.0 + golang.org/x/text v0.16.0 golang.org/x/time v0.5.0 - golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 + golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 golang.zx2c4.com/wireguard v0.0.0-20220920152132-bb719d3a6e2c golang.zx2c4.com/wireguard/windows v0.5.3 google.golang.org/grpc v1.62.1 google.golang.org/protobuf v1.33.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 - gvisor.dev/gvisor v0.0.0-20240403010941-979aae3d2c21 + gvisor.dev/gvisor v0.0.0-20240722211153-64c016c92987 k8s.io/api v0.31.0-alpha.0 k8s.io/apimachinery v0.31.0-alpha.0 k8s.io/cli-runtime v0.29.3 k8s.io/client-go v0.31.0-alpha.0 - k8s.io/klog/v2 v2.120.1 + k8s.io/klog/v2 v2.130.1 k8s.io/kubectl v0.29.3 - k8s.io/utils v0.0.0-20240310230437-4693a0247e57 - sigs.k8s.io/controller-runtime v0.17.1-0.20240327193027-21368602d84b + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 + sigs.k8s.io/controller-runtime v0.18.4 sigs.k8s.io/kustomize/api v0.16.0 sigs.k8s.io/yaml v1.4.0 - tags.cncf.io/container-device-interface v0.7.0 + tailscale.com v1.72.1 ) require ( @@ -71,6 +70,7 @@ require ( cloud.google.com/go/compute v1.25.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect dario.cat/mergo v1.0.0 // indirect + filippo.io/edwards25519 v1.1.0 // indirect github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect @@ -94,10 +94,12 @@ require ( github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.12.2 // indirect + github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect github.com/antonmedv/expr v1.15.5 // indirect github.com/apparentlymart/go-cidr v1.1.0 // indirect github.com/aws/aws-sdk-go v1.51.12 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/calmh/incontainer v1.0.0 // indirect github.com/calmh/xdr v1.1.0 // indirect github.com/ccding/go-stun v0.1.4 // indirect @@ -107,9 +109,11 @@ require ( github.com/chmduquesne/rollinghash v4.0.0+incompatible // indirect github.com/cncf/xds/go v0.0.0-20240329184929-0c46c01016dc // indirect github.com/containerd/log v0.1.0 // indirect + github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa // indirect github.com/dimchansky/utfbom v1.1.1 // indirect github.com/dnstap/golang-dnstap v0.4.0 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect @@ -129,10 +133,13 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect + github.com/fxamacker/cbor/v2 v2.6.0 // indirect + github.com/gaissmai/bart v0.11.1 // indirect github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect github.com/go-errors/errors v1.5.1 // indirect + github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0 // indirect github.com/go-ldap/ldap/v3 v3.4.6 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect @@ -140,16 +147,18 @@ require ( github.com/go-openapi/swag v0.23.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gobwas/glob v0.2.3 // indirect + github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f // indirect + github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 // indirect + github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect @@ -163,6 +172,8 @@ require ( github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hdevalence/ed25519consensus v0.2.0 // indirect + github.com/illarion/gonotify v1.0.1 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/infobloxopen/go-trees v0.0.0-20221216143356-66ceba885ebc // indirect @@ -174,6 +185,8 @@ require ( github.com/jcmturner/rpc/v2 v2.0.3 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect + github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 // indirect + github.com/jsimonetti/rtnetlink v1.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect @@ -182,6 +195,8 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mdlayher/netlink v1.7.2 // indirect + github.com/mdlayher/socket v0.5.0 // indirect github.com/miekg/pkcs11 v1.1.1 // indirect github.com/minio/sha256-simd v1.0.1 // indirect github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 // indirect @@ -215,7 +230,7 @@ require ( github.com/pierrec/lz4/v4 v4.1.21 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/prometheus/client_golang v1.19.0 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.52.2 // indirect github.com/prometheus/procfs v0.13.0 // indirect @@ -229,9 +244,13 @@ require ( github.com/stretchr/testify v1.9.0 // indirect github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect + github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 // indirect github.com/theupdateframework/notary v0.7.0 // indirect github.com/tinylib/msgp v1.1.9 // indirect + github.com/vishvananda/netlink v1.2.1-beta.2 // indirect + github.com/vishvananda/netns v0.0.4 // indirect github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0 // indirect + github.com/x448/float16 v0.8.4 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -251,10 +270,13 @@ require ( go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/tools v0.21.0 // indirect - golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect + go4.org/mem v0.0.0-20220726221520-4f986261bf13 // indirect + go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect + golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/term v0.22.0 // indirect + golang.org/x/tools v0.23.0 // indirect + golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/api v0.172.0 // indirect google.golang.org/appengine v1.6.8 // indirect diff --git a/go.sum b/go.sum index 72cde884..b6ee1916 100644 --- a/go.sum +++ b/go.sum @@ -7,6 +7,8 @@ cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGB cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= @@ -41,8 +43,6 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/DataDog/appsec-internal-go v1.5.0 h1:8kS5zSx5T49uZ8dZTdT19QVAvC/B8ByyZdhQKYQWHno= github.com/DataDog/appsec-internal-go v1.5.0/go.mod h1:pEp8gjfNLtEOmz+iZqC8bXhu0h4k7NUsW/qiQb34k1U= github.com/DataDog/datadog-agent/pkg/obfuscate v0.52.0 h1:J2iRNRgtKsLq3L55NJzZMQqTqbm8+ps8iKCwjkCph9E= @@ -90,6 +90,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= +github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0 h1:s7+5BfS4WFJoVF9pnB8kBk03S7pZXRdKamnV0FOl5Sc= github.com/bugsnag/bugsnag-go v1.0.5-0.20150529004307-13fd6b8acda0/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= @@ -119,6 +121,8 @@ github.com/chmduquesne/rollinghash v4.0.0+incompatible/go.mod h1:Uc2I36RRfTAf7Dg github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.15.0 h1:7NxJhNiBT3NG8pZJ3c+yfrVdHY8ScgKD27sScgjLMMk= +github.com/cilium/ebpf v0.15.0/go.mod h1:DHp1WyrLeiBh19Cf/tfiSMhqheEiK8fXFZ4No0P1Hso= github.com/cilium/ipam v0.0.0-20230509084518-fd66eae7909b h1:yTDNdo6hd8ABJYeLUvmqKAYj3jaRzLYx3UwM+/jSeBY= github.com/cilium/ipam v0.0.0-20230509084518-fd66eae7909b/go.mod h1:Ascfar4FtgB+K+mwqbZpSb3WVZ5sPFIarg+iAOXNZqI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -137,20 +141,24 @@ github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0= github.com/coredns/caddy v1.1.1/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coredns/coredns v1.11.2 h1:HnCGNxSolDRge1fhQD1/N7AzYfStLMtqVAmuUe1jo1I= github.com/coredns/coredns v1.11.2/go.mod h1:EqOuX/f6iSRMG18JBwkS0Ern3iV9ImS+hZHgVuwGt+0= +github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6 h1:8h5+bWd7R6AYUslN6c6iuZWTKsKxUFDlpnmilO6R2n0= +github.com/coreos/go-iptables v0.7.1-0.20240112124308-65c67c9f46e6/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= -github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/creack/pty v1.1.23 h1:4M6+isWdcStXEf15G/RbrMPOQj1dZ7HPZCGwE4kOeP0= +github.com/creack/pty v1.1.23/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U= github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa h1:h8TfIT1xc8FWbwwpmHn1J5i43Y0uZP97GqasGCzSRJk= +github.com/dblohm7/wingoes v0.0.0-20240119213807-a09d6be7affa/go.mod h1:Nx87SkVqTKd8UtT+xu7sM/l+LgXs6c0aHrlKusR+2EQ= github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= @@ -165,8 +173,8 @@ github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvM github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU= -github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU= +github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= @@ -214,6 +222,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= @@ -221,18 +231,24 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= +github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/gaissmai/bart v0.11.1 h1:5Uv5XwsaFBRo4E5VBcb9TzY8B7zxFf+U7isDxqOrRfc= +github.com/gaissmai/bart v0.11.1/go.mod h1:KHeYECXQiBjTzQz/om2tqn3sZF1J7hw9m6z41ftj3fg= github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0 h1:ymLjT4f35nQbASLnvxEde4XOBL+Sn7rFuV+FOJqkljg= +github.com/go-json-experiment/json v0.0.0-20231102232822-2e55bd4e08b0/go.mod h1:6daplAwHHGbUGib4990V3Il26O0OC4aRyvewaaAihaA= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A= github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -256,6 +272,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4 github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 h1:sQspH8M4niEijh3PFscJRLDnkL547IeP7kpPe3uUhEg= +github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466/go.mod h1:ZiQxhyQ+bbbfxUKVvjfO498oPYvtYhZzycal3G/NHmU= github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -293,8 +311,8 @@ github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93 h1:jc2UWq7CbdszqeH6qu1ougXMIUBfSy8Pbh/anURYbGI= github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519c93/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= +github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -311,9 +329,11 @@ github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806 h1:wG8RYIyctLhdFk6Vl1yPGtSRtwGpVkWyZww1OCil2MI= +github.com/google/nftables v0.2.1-0.20240414091927-5e242ec57806/go.mod h1:Beg6V6zZ3oEn0JuiUQ4wqwuyqqzasOltcoXPtgLbFp4= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f h1:f00RU+zOX+B3rLAmMMkzHUF2h1z4DeYR9tTCvEq2REY= -github.com/google/pprof v0.0.0-20240402174815-29b9bb013b0f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= @@ -330,8 +350,9 @@ github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBH github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= +github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -360,9 +381,15 @@ github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mO github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= +github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= +github.com/hdevalence/ed25519consensus v0.2.0 h1:37ICyZqdyj0lAZ8P4D1d1id3HqbbG1N3iBb1Tb4rdcU= +github.com/hdevalence/ed25519consensus v0.2.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/illarion/gonotify v1.0.1 h1:F1d+0Fgbq/sDWjj/r66ekjDG+IDeecQKUFH4wNwsoio= +github.com/illarion/gonotify v1.0.1/go.mod h1:zt5pmDofZpU1f8aqlK0+95eQhoEAn/d4G4B/FjVW4jE= github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -399,6 +426,10 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 h1:elKwZS1OcdQ0WwEDBeqxKwb7WB62QX8bvZ/FJnVXIfk= +github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86/go.mod h1:aFAMtuldEgx/4q7iSGazk22+IcgvtiC+HIimFO9XlS8= +github.com/jsimonetti/rtnetlink v1.4.0 h1:Z1BF0fRgcETPEa0Kt0MRk3yV5+kF1FWTni6KUFKrq2I= +github.com/jsimonetti/rtnetlink v1.4.0/go.mod h1:5W1jDvWdnthFJ7fxYX1GMK07BUpI4oskfOqvPteYS6E= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -434,8 +465,9 @@ github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDT github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/magiconair/properties v1.5.3 h1:C8fxWnhYyME3n0klPOhVM7PtYUB3eV1W3DeFmN3j53Y= github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattbaird/jsonpatch v0.0.0-20240118010651-0ba75a80ca38 h1:hQWBtNqRYrI7CWIaUSXXtNKR90KzcUA5uiuxFVWw7sU= @@ -447,6 +479,10 @@ github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOq github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.5.0 h1:ilICZmJcQz70vrWVes1MFera4jGiWNocSkykwwoy3XI= +github.com/mdlayher/socket v0.5.0/go.mod h1:WkcBFfvyG8QENs5+hfQPl1X6Jpd2yeLIYgrGFmJiJxI= github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= @@ -540,6 +576,9 @@ github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq5 github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY= github.com/outcaste-io/ristretto v0.2.3 h1:AK4zt/fJ76kjlYObOeNwh4T3asEuaCmp26pOvUOL9w0= github.com/outcaste-io/ristretto v0.2.3/go.mod h1:W8HywhmtlopSB1jeMg3JtdIhf+DYkLAr0VN/s4+MHac= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= +github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= @@ -564,8 +603,8 @@ github.com/prometheus/client_golang v0.9.0-pre1.0.20180209125602-c332b6f63c06/go github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= -github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= -github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -600,8 +639,8 @@ github.com/schollz/progressbar/v3 v3.14.2 h1:EducH6uNLIWsr560zSV1KrTeUb/wZGAHqyM github.com/schollz/progressbar/v3 v3.14.2/go.mod h1:aQAZQnhF4JGFtRJiw/eobaXpsqpVQAftEQ+hLGXaRc4= github.com/secure-systems-lab/go-securesystemslib v0.8.0 h1:mr5An6X45Kb2nddcFlbmfHkLguCE9laoZCUzEEpIZXA= github.com/secure-systems-lab/go-securesystemslib v0.8.0/go.mod h1:UH2VZVuJfCYR8WgMlCU1uFsOUU+KeyrTWcSS73NBOzU= -github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= github.com/shirou/gopsutil/v3 v3.24.3/go.mod h1:JpND7O217xa72ewWz9zN2eIIkPWsDN/3pl0H8Qt0uwg= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= @@ -614,18 +653,23 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94 h1:JmfC365KywYwHB946TTiQWEb8kqPY+pybPLoGE9GgVk= +github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY= +github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= -github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431 h1:XTHrT015sxHyJ5FnQ0AeemSspZWaDq7DoTRW0EVsDCE= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c h1:2EejZtjFjKJGk71ANb+wtFK5EjUzUkEM3R0xnp559xg= github.com/spf13/viper v0.0.0-20150530192845-be5ff3e4840c/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= +github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc= +github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -647,12 +691,16 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2 h1:F4snRP//nIuTTW9LYEzVH4HVwDG9T3M4t8y/2nqMbiY= github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2/go.mod h1:J0q59IWjLtpRIJulohwqEZvjzwOfTEPp8SVhDJl+y0Y= github.com/syncthing/syncthing v1.27.7 h1:N06QpAUPQi2VaB+X0wko5h8JtH3qJP5Dd4MYq952pEw= github.com/syncthing/syncthing v1.27.7/go.mod h1:bMhGhc70k3UFszFhmCVNxM5bOsDfhxYMHvj4lWlIYBk= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 h1:zrsUcqrG2uQSPhaUPjUQwozcRdDdSxxqhNgNZ3drZFk= +github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85/go.mod h1:NzVQi3Mleb+qzq8VmcWpSkcSYxXIg0DkI6XDzpVkhJ0= github.com/thejerf/suture/v4 v4.0.5 h1:F1E/4FZwXWqvlWDKEUo6/ndLtxGAUzMmNqkrMknZbAA= github.com/thejerf/suture/v4 v4.0.5/go.mod h1:gu9Y4dXNUWFrByqRt30Rm9/UZ0wzRSt9AJS6xu/ZGxU= github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= @@ -661,8 +709,15 @@ github.com/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU= github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs= +github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= +github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0 h1:okhMind4q9H1OxF44gNegWkiP4H/gsTFLalHFa4OOUI= github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0/go.mod h1:TTbGUfE+cXXceWtbTHq6lqcTvYPBKLNejBEbnUsQJtU= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -717,6 +772,10 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go4.org/mem v0.0.0-20220726221520-4f986261bf13 h1:CbZeCBZ0aZj8EfVgnqQcYZgf0lpZ3H9rmp5nkDTAst8= +go4.org/mem v0.0.0-20220726221520-4f986261bf13/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= +go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= +go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -729,8 +788,8 @@ golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0 h1:985EYyeCOxTpcgOTJpflJUwOeEz0CQOdPt73OzpE9F8= golang.org/x/exp v0.0.0-20240404231335-c0f41cb1a7a0/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= @@ -744,8 +803,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -771,8 +830,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= @@ -802,7 +861,9 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -820,7 +881,9 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220817070843-5a390386f1f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -828,8 +891,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -837,8 +900,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -847,8 +910,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -865,17 +928,17 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= -golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY= -golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= +golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 h1:LLhsEBxRTBLuKlQxFBYUOU8xyFgXv6cOTp2HASDlsDk= +golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= +golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard v0.0.0-20220920152132-bb719d3a6e2c h1:Okh6a1xpnJslG9Mn84pId1Mn+Q8cvpo4HCeeFWHo0cA= golang.zx2c4.com/wireguard v0.0.0-20220920152132-bb719d3a6e2c/go.mod h1:enML0deDxY1ux+B6ANGiwtg0yAJi1rctkTpcHNAVPyg= golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE= @@ -934,6 +997,8 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/rethinkdb/rethinkdb-go.v6 v6.2.1 h1:d4KQkxAaAiRY2h5Zqis161Pv91A37uZyJOx73duwUwM= @@ -952,8 +1017,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= -gvisor.dev/gvisor v0.0.0-20240403010941-979aae3d2c21 h1:bH3op9vONK524+xoo4oiJR+LHMH4g58y0VZIao4eWvU= -gvisor.dev/gvisor v0.0.0-20240403010941-979aae3d2c21/go.mod h1:NQHVAzMwvZ+Qe3ElSiHmq9RUm1MdNHpUZ52fiEqvn+0= +gvisor.dev/gvisor v0.0.0-20240722211153-64c016c92987 h1:TU8z2Lh3Bbq77w0t1eG8yRlLcNHzZu3x6mhoH2Mk0c8= +gvisor.dev/gvisor v0.0.0-20240722211153-64c016c92987/go.mod h1:sxc3Uvk/vHcd3tj7/DHVBoR5wvWT/MmRq2pj7HRJnwU= honnef.co/go/gotraceui v0.2.0 h1:dmNsfQ9Vl3GwbiVD7Z8d/osC6WtGGrasyrC2suc4ZIQ= honnef.co/go/gotraceui v0.2.0/go.mod h1:qHo4/W75cA3bX0QQoSvDjbJa4R8mAyyFjbWAj63XElc= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -970,16 +1035,16 @@ k8s.io/client-go v0.31.0-alpha.0 h1:VVxcVKbqni0wAWd3rNuXcNcpE7gT6jvVLBe/YlWKu8s= k8s.io/client-go v0.31.0-alpha.0/go.mod h1:XM6Bsdnz08pV+PfIUNDOgblfG6PVLI9ll6xHMk1Ifso= k8s.io/component-base v0.31.0-alpha.0 h1:Wm2aXDIEXja0o6p/w3+MCAvvfQyvKRWEfSl82wdr1Bo= k8s.io/component-base v0.31.0-alpha.0/go.mod h1:MDaPQWtkCUMorX4RRF32PA4rYGmVx9k5uPIze58kixM= -k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= -k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940 h1:qVoMaQV5t62UUvHe16Q3eb2c5HPzLHYzsi0Tu/xLndo= k8s.io/kube-openapi v0.0.0-20240322212309-b815d8309940/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/kubectl v0.29.3 h1:RuwyyIU42MAISRIePaa8Q7A3U74Q9P4MoJbDFz9o3us= k8s.io/kubectl v0.29.3/go.mod h1:yCxfY1dbwgVdEt2zkJ6d5NNLOhhWgTyrqACIoFhpdd4= -k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0gQBEuevE/AaBsHY= -k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.17.1-0.20240327193027-21368602d84b h1:ZQ+OFhT7H5LX/MrAYqJK9NWgyAEituKyU5XO2KQdHpo= -sigs.k8s.io/controller-runtime v0.17.1-0.20240327193027-21368602d84b/go.mod h1:J31OHxL1QGCaT4cf24B9kcx8E2l7ohnVG4zxzlCuA9o= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.18.4 h1:87+guW1zhvuPLh1PHybKdYFLU0YJp4FhJRmiHvm5BZw= +sigs.k8s.io/controller-runtime v0.18.4/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/kustomize/api v0.16.0 h1:/zAR4FOQDCkgSDmVzV2uiFbuy9bhu3jEzthrHCuvm1g= @@ -990,5 +1055,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+s sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= -tags.cncf.io/container-device-interface v0.7.0 h1:9z94b0DPipEWShy5nct34ZRx5QnDxHXxhSTdkTr+k1c= -tags.cncf.io/container-device-interface v0.7.0/go.mod h1:PZsuvtfPi0YOYD1hvulncIT7R7YoiZY7eOsrsllQPe4= +tailscale.com v1.72.1 h1:hk82jek36ph2S3Tfsh57NVWKEm/pZ9nfUonvlowpfaA= +tailscale.com v1.72.1/go.mod h1:v7OHtg0KLAnhOVf81Z8WrjNefj238QbFhgkWJQoKxbs= diff --git a/pkg/core/gvisorstack.go b/pkg/core/gvisorstack.go index 30388c1d..a7346763 100755 --- a/pkg/core/gvisorstack.go +++ b/pkg/core/gvisorstack.go @@ -15,15 +15,6 @@ import ( "gvisor.dev/gvisor/pkg/tcpip/transport/udp" ) -var _ stack.UniqueID = (*ID)(nil) - -type ID struct { -} - -func (i ID) UniqueID() uint64 { - return 1 -} - func NewStack(ctx context.Context, tun stack.LinkEndpoint) *stack.Stack { s := stack.New(stack.Options{ NetworkProtocols: []stack.NetworkProtocolFactory{ @@ -40,7 +31,6 @@ func NewStack(ctx context.Context, tun stack.LinkEndpoint) *stack.Stack { // Enable raw sockets for users with sufficient // privileges. RawFactory: raw.EndpointFactory{}, - UniqueID: ID{}, }) // set handler for TCP UDP ICMP s.SetTransportProtocolHandler(tcp.ProtocolNumber, TCPForwarder(s)) diff --git a/pkg/dns/dns.go b/pkg/dns/dns.go index 37689e63..f26aa7ff 100644 --- a/pkg/dns/dns.go +++ b/pkg/dns/dns.go @@ -24,6 +24,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/watch" v13 "k8s.io/client-go/kubernetes/typed/core/v1" + "tailscale.com/net/dns" "github.com/wencaiwulue/kubevpn/v2/pkg/config" ) @@ -35,6 +36,9 @@ type Config struct { Hosts []Entry Lock *sync.Mutex + + // only set it on linux + OSConfigurator dns.OSConfigurator } func (c *Config) AddServiceNameToHosts(ctx context.Context, serviceInterface v13.ServiceInterface, hosts ...Entry) error { diff --git a/pkg/dns/dns_linux.go b/pkg/dns/dns_linux.go index c858348b..f3675abd 100644 --- a/pkg/dns/dns_linux.go +++ b/pkg/dns/dns_linux.go @@ -5,7 +5,10 @@ package dns import ( "bytes" "context" + "errors" "fmt" + "net" + "net/netip" "os" "os/exec" "strings" @@ -17,13 +20,16 @@ import ( miekgdns "github.com/miekg/dns" log "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/util/sets" + "tailscale.com/net/dns" + "tailscale.com/util/dnsname" ) +// SetupDNS // systemd-resolve --status, systemd-resolve --flush-caches func (c *Config) SetupDNS(ctx context.Context) error { - clientConfig := c.Config + config := c.Config tunName := c.TunName - + log.Debugf("Setting up DNS...") // TODO consider use https://wiki.debian.org/NetworkManager and nmcli to config DNS // try to solve: // sudo systemd-resolve --set-dns 172.28.64.10 --interface tun0 --set-domain=vke-system.svc.cluster.local --set-domain=svc.cluster.local --set-domain=cluster.local @@ -35,21 +41,35 @@ func (c *Config) SetupDNS(ctx context.Context) error { _ = exec.Command("systemctl", "start", "systemd-resolved.service").Run() //systemctl status systemd-resolved.service _ = exec.Command("systemctl", "status", "systemd-resolved.service").Run() - - cmd := exec.Command("systemd-resolve", []string{ - "--set-dns", - clientConfig.Servers[0], - "--interface", - tunName, - "--set-domain=" + clientConfig.Search[0], - "--set-domain=" + clientConfig.Search[1], - "--set-domain=" + clientConfig.Search[2], - }...) - output, err := cmd.CombinedOutput() - if err != nil { - log.Debugf("Failed to exec cmd: %s, message: %s, ignore", strings.Join(cmd.Args, " "), string(output)) - err = nil + log.Debugf("Enable service systemd resolved...") + var exists = func(cmd string) bool { + _, err := exec.LookPath(cmd) + return err == nil } + log.Debugf("Try to setup DNS by resolvectl or systemd-resolve...") + if exists("resolvectl") { + _ = GetResolveCtlCmd(ctx, tunName, config) + } + if exists("systemd-resolve") { + _ = GetSystemdResolveCmd(ctx, tunName, config) + } + + log.Debugf("Use library to setup DNS...") + // https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#default-environment-variables + if _, found := os.LookupEnv("GITHUB_ACTIONS"); !found { + err := c.UseLibraryDNS(tunName, config) + if err == nil { + log.Debugf("Use library to setup DNS done") + return nil + } else if errors.Is(err, ErrorNotSupportSplitDNS) { + log.Debugf("Library not support on current OS") + err = nil + } else { + log.Errorf("Setup DNS by library failed: %v", err) + err = nil + } + } + filename := resolvconf.Path() readFile, err := os.ReadFile(filename) @@ -60,11 +80,77 @@ func (c *Config) SetupDNS(ctx context.Context) error { if err != nil { return err } - localResolvConf.Servers = append([]string{clientConfig.Servers[0]}, localResolvConf.Servers...) - err = WriteResolvConf(*localResolvConf) + localResolvConf.Servers = append([]string{config.Servers[0]}, localResolvConf.Servers...) + err = WriteResolvConf(resolvconf.Path(), *localResolvConf) return err } +// GetResolveCtlCmd +// resolvectl dns utun0 10.10.129.161 +// resolvectl domain utun0 default.svc.cluster.local svc.cluster.local cluster.local +func GetResolveCtlCmd(ctx context.Context, tunName string, config *miekgdns.ClientConfig) error { + cmd := exec.CommandContext(ctx, "resolvectl", "dns", tunName, config.Servers[0]) + output, err := cmd.CombinedOutput() + if err != nil { + log.Debugf("Failed to exec cmd '%s': %s", strings.Join(cmd.Args, " "), string(output)) + return err + } + cmd = exec.CommandContext(ctx, "resolvectl", "domain", tunName, config.Search[0], config.Search[1], config.Search[2]) + output, err = cmd.CombinedOutput() + if err != nil { + log.Debugf("Failed to exec cmd '%s': %s", strings.Join(cmd.Args, " "), string(output)) + return err + } + return nil +} + +func GetSystemdResolveCmd(ctx context.Context, tunName string, config *miekgdns.ClientConfig) error { + cmd := exec.CommandContext(ctx, "systemd-resolve", []string{ + "--set-dns", + config.Servers[0], + "--interface", + tunName, + "--set-domain=" + config.Search[0], + "--set-domain=" + config.Search[1], + "--set-domain=" + config.Search[2], + }...) + output, err := cmd.CombinedOutput() + if err != nil { + log.Debugf("Failed to exec cmd '%s': %s", strings.Join(cmd.Args, " "), string(output)) + } + return err +} + +var ErrorNotSupportSplitDNS = errors.New("not support split DNS") + +func (c *Config) UseLibraryDNS(tunName string, clientConfig *miekgdns.ClientConfig) error { + configurator, err := dns.NewOSConfigurator(log.Debugf, nil, nil, tunName) + if err != nil { + return err + } + if !configurator.SupportsSplitDNS() { + return ErrorNotSupportSplitDNS + } + c.OSConfigurator = configurator + config := dns.OSConfig{Nameservers: []netip.Addr{}, SearchDomains: []dnsname.FQDN{}} + for _, s := range clientConfig.Servers { + ip, ok := netip.AddrFromSlice(net.ParseIP(s)) + if !ok { + continue + } + config.Nameservers = append(config.Nameservers, ip) + } + for _, search := range clientConfig.Search { + fqdn, err := dnsname.ToFQDN(search) + if err != nil { + continue + } + config.SearchDomains = append(config.SearchDomains, fqdn) + } + log.Debugf("Setting up DNS...") + return c.OSConfigurator.SetDNS(config) +} + func SetupLocalDNS(ctx context.Context, clientConfig *miekgdns.ClientConfig, existNameservers []string) error { corefile, err := BuildCoreFile(CoreFileTmpl{ UpstreamDNS: clientConfig.Servers[0], @@ -93,6 +179,9 @@ func SetupLocalDNS(ctx context.Context, clientConfig *miekgdns.ClientConfig, exi func (c *Config) CancelDNS() { c.removeHosts(sets.New[Entry]().Insert(c.Hosts...).UnsortedList()) + if c.OSConfigurator != nil { + _ = c.OSConfigurator.Close() + } filename := resolvconf.Path() readFile, err := os.ReadFile(filename) @@ -110,7 +199,7 @@ func (c *Config) CancelDNS() { break } } - err = WriteResolvConf(*resolvConf) + err = WriteResolvConf(resolvconf.Path(), *resolvConf) if err != nil { log.Warnf("Failed to remove DNS from resolv conf file: %v", err) } @@ -120,7 +209,7 @@ func GetHostFile() string { return "/etc/hosts" } -func WriteResolvConf(config miekgdns.ClientConfig) error { +func WriteResolvConf(filename string, config miekgdns.ClientConfig) error { var options []string if config.Ndots != 0 { options = append(options, fmt.Sprintf("ndots:%d", config.Ndots)) @@ -132,7 +221,6 @@ func WriteResolvConf(config miekgdns.ClientConfig) error { options = append(options, fmt.Sprintf("timeout:%d", config.Timeout)) } - filename := resolvconf.Path() _, err := resolvconf.Build(filename, config.Servers, config.Search, options) return err } diff --git a/vendor/filippo.io/edwards25519/LICENSE b/vendor/filippo.io/edwards25519/LICENSE new file mode 100644 index 00000000..6a66aea5 --- /dev/null +++ b/vendor/filippo.io/edwards25519/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/filippo.io/edwards25519/README.md b/vendor/filippo.io/edwards25519/README.md new file mode 100644 index 00000000..24e2457d --- /dev/null +++ b/vendor/filippo.io/edwards25519/README.md @@ -0,0 +1,14 @@ +# filippo.io/edwards25519 + +``` +import "filippo.io/edwards25519" +``` + +This library implements the edwards25519 elliptic curve, exposing the necessary APIs to build a wide array of higher-level primitives. +Read the docs at [pkg.go.dev/filippo.io/edwards25519](https://pkg.go.dev/filippo.io/edwards25519). + +The code is originally derived from Adam Langley's internal implementation in the Go standard library, and includes George Tankersley's [performance improvements](https://golang.org/cl/71950). It was then further developed by Henry de Valence for use in ristretto255, and was finally [merged back into the Go standard library](https://golang.org/cl/276272) as of Go 1.17. It now tracks the upstream codebase and extends it with additional functionality. + +Most users don't need this package, and should instead use `crypto/ed25519` for signatures, `golang.org/x/crypto/curve25519` for Diffie-Hellman, or `github.com/gtank/ristretto255` for prime order group logic. However, for anyone currently using a fork of `crypto/internal/edwards25519`/`crypto/ed25519/internal/edwards25519` or `github.com/agl/edwards25519`, this package should be a safer, faster, and more powerful alternative. + +Since this package is meant to curb proliferation of edwards25519 implementations in the Go ecosystem, it welcomes requests for new APIs or reviewable performance improvements. diff --git a/vendor/filippo.io/edwards25519/doc.go b/vendor/filippo.io/edwards25519/doc.go new file mode 100644 index 00000000..ab6aaebc --- /dev/null +++ b/vendor/filippo.io/edwards25519/doc.go @@ -0,0 +1,20 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package edwards25519 implements group logic for the twisted Edwards curve +// +// -x^2 + y^2 = 1 + -(121665/121666)*x^2*y^2 +// +// This is better known as the Edwards curve equivalent to Curve25519, and is +// the curve used by the Ed25519 signature scheme. +// +// Most users don't need this package, and should instead use crypto/ed25519 for +// signatures, golang.org/x/crypto/curve25519 for Diffie-Hellman, or +// github.com/gtank/ristretto255 for prime order group logic. +// +// However, developers who do need to interact with low-level edwards25519 +// operations can use this package, which is an extended version of +// crypto/internal/edwards25519 from the standard library repackaged as +// an importable module. +package edwards25519 diff --git a/vendor/filippo.io/edwards25519/edwards25519.go b/vendor/filippo.io/edwards25519/edwards25519.go new file mode 100644 index 00000000..a744da2c --- /dev/null +++ b/vendor/filippo.io/edwards25519/edwards25519.go @@ -0,0 +1,427 @@ +// Copyright (c) 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "errors" + + "filippo.io/edwards25519/field" +) + +// Point types. + +type projP1xP1 struct { + X, Y, Z, T field.Element +} + +type projP2 struct { + X, Y, Z field.Element +} + +// Point represents a point on the edwards25519 curve. +// +// This type works similarly to math/big.Int, and all arguments and receivers +// are allowed to alias. +// +// The zero value is NOT valid, and it may be used only as a receiver. +type Point struct { + // Make the type not comparable (i.e. used with == or as a map key), as + // equivalent points can be represented by different Go values. + _ incomparable + + // The point is internally represented in extended coordinates (X, Y, Z, T) + // where x = X/Z, y = Y/Z, and xy = T/Z per https://eprint.iacr.org/2008/522. + x, y, z, t field.Element +} + +type incomparable [0]func() + +func checkInitialized(points ...*Point) { + for _, p := range points { + if p.x == (field.Element{}) && p.y == (field.Element{}) { + panic("edwards25519: use of uninitialized Point") + } + } +} + +type projCached struct { + YplusX, YminusX, Z, T2d field.Element +} + +type affineCached struct { + YplusX, YminusX, T2d field.Element +} + +// Constructors. + +func (v *projP2) Zero() *projP2 { + v.X.Zero() + v.Y.One() + v.Z.One() + return v +} + +// identity is the point at infinity. +var identity, _ = new(Point).SetBytes([]byte{ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) + +// NewIdentityPoint returns a new Point set to the identity. +func NewIdentityPoint() *Point { + return new(Point).Set(identity) +} + +// generator is the canonical curve basepoint. See TestGenerator for the +// correspondence of this encoding with the values in RFC 8032. +var generator, _ = new(Point).SetBytes([]byte{ + 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}) + +// NewGeneratorPoint returns a new Point set to the canonical generator. +func NewGeneratorPoint() *Point { + return new(Point).Set(generator) +} + +func (v *projCached) Zero() *projCached { + v.YplusX.One() + v.YminusX.One() + v.Z.One() + v.T2d.Zero() + return v +} + +func (v *affineCached) Zero() *affineCached { + v.YplusX.One() + v.YminusX.One() + v.T2d.Zero() + return v +} + +// Assignments. + +// Set sets v = u, and returns v. +func (v *Point) Set(u *Point) *Point { + *v = *u + return v +} + +// Encoding. + +// Bytes returns the canonical 32-byte encoding of v, according to RFC 8032, +// Section 5.1.2. +func (v *Point) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var buf [32]byte + return v.bytes(&buf) +} + +func (v *Point) bytes(buf *[32]byte) []byte { + checkInitialized(v) + + var zInv, x, y field.Element + zInv.Invert(&v.z) // zInv = 1 / Z + x.Multiply(&v.x, &zInv) // x = X / Z + y.Multiply(&v.y, &zInv) // y = Y / Z + + out := copyFieldElement(buf, &y) + out[31] |= byte(x.IsNegative() << 7) + return out +} + +var feOne = new(field.Element).One() + +// SetBytes sets v = x, where x is a 32-byte encoding of v. If x does not +// represent a valid point on the curve, SetBytes returns nil and an error and +// the receiver is unchanged. Otherwise, SetBytes returns v. +// +// Note that SetBytes accepts all non-canonical encodings of valid points. +// That is, it follows decoding rules that match most implementations in +// the ecosystem rather than RFC 8032. +func (v *Point) SetBytes(x []byte) (*Point, error) { + // Specifically, the non-canonical encodings that are accepted are + // 1) the ones where the field element is not reduced (see the + // (*field.Element).SetBytes docs) and + // 2) the ones where the x-coordinate is zero and the sign bit is set. + // + // Read more at https://hdevalence.ca/blog/2020-10-04-its-25519am, + // specifically the "Canonical A, R" section. + + y, err := new(field.Element).SetBytes(x) + if err != nil { + return nil, errors.New("edwards25519: invalid point encoding length") + } + + // -x² + y² = 1 + dx²y² + // x² + dx²y² = x²(dy² + 1) = y² - 1 + // x² = (y² - 1) / (dy² + 1) + + // u = y² - 1 + y2 := new(field.Element).Square(y) + u := new(field.Element).Subtract(y2, feOne) + + // v = dy² + 1 + vv := new(field.Element).Multiply(y2, d) + vv = vv.Add(vv, feOne) + + // x = +√(u/v) + xx, wasSquare := new(field.Element).SqrtRatio(u, vv) + if wasSquare == 0 { + return nil, errors.New("edwards25519: invalid point encoding") + } + + // Select the negative square root if the sign bit is set. + xxNeg := new(field.Element).Negate(xx) + xx = xx.Select(xxNeg, xx, int(x[31]>>7)) + + v.x.Set(xx) + v.y.Set(y) + v.z.One() + v.t.Multiply(xx, y) // xy = T / Z + + return v, nil +} + +func copyFieldElement(buf *[32]byte, v *field.Element) []byte { + copy(buf[:], v.Bytes()) + return buf[:] +} + +// Conversions. + +func (v *projP2) FromP1xP1(p *projP1xP1) *projP2 { + v.X.Multiply(&p.X, &p.T) + v.Y.Multiply(&p.Y, &p.Z) + v.Z.Multiply(&p.Z, &p.T) + return v +} + +func (v *projP2) FromP3(p *Point) *projP2 { + v.X.Set(&p.x) + v.Y.Set(&p.y) + v.Z.Set(&p.z) + return v +} + +func (v *Point) fromP1xP1(p *projP1xP1) *Point { + v.x.Multiply(&p.X, &p.T) + v.y.Multiply(&p.Y, &p.Z) + v.z.Multiply(&p.Z, &p.T) + v.t.Multiply(&p.X, &p.Y) + return v +} + +func (v *Point) fromP2(p *projP2) *Point { + v.x.Multiply(&p.X, &p.Z) + v.y.Multiply(&p.Y, &p.Z) + v.z.Square(&p.Z) + v.t.Multiply(&p.X, &p.Y) + return v +} + +// d is a constant in the curve equation. +var d, _ = new(field.Element).SetBytes([]byte{ + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, + 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, + 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52}) +var d2 = new(field.Element).Add(d, d) + +func (v *projCached) FromP3(p *Point) *projCached { + v.YplusX.Add(&p.y, &p.x) + v.YminusX.Subtract(&p.y, &p.x) + v.Z.Set(&p.z) + v.T2d.Multiply(&p.t, d2) + return v +} + +func (v *affineCached) FromP3(p *Point) *affineCached { + v.YplusX.Add(&p.y, &p.x) + v.YminusX.Subtract(&p.y, &p.x) + v.T2d.Multiply(&p.t, d2) + + var invZ field.Element + invZ.Invert(&p.z) + v.YplusX.Multiply(&v.YplusX, &invZ) + v.YminusX.Multiply(&v.YminusX, &invZ) + v.T2d.Multiply(&v.T2d, &invZ) + return v +} + +// (Re)addition and subtraction. + +// Add sets v = p + q, and returns v. +func (v *Point) Add(p, q *Point) *Point { + checkInitialized(p, q) + qCached := new(projCached).FromP3(q) + result := new(projP1xP1).Add(p, qCached) + return v.fromP1xP1(result) +} + +// Subtract sets v = p - q, and returns v. +func (v *Point) Subtract(p, q *Point) *Point { + checkInitialized(p, q) + qCached := new(projCached).FromP3(q) + result := new(projP1xP1).Sub(p, qCached) + return v.fromP1xP1(result) +} + +func (v *projP1xP1) Add(p *Point, q *projCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YplusX) + MM.Multiply(&YminusX, &q.YminusX) + TT2d.Multiply(&p.t, &q.T2d) + ZZ2.Multiply(&p.z, &q.Z) + + ZZ2.Add(&ZZ2, &ZZ2) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Add(&ZZ2, &TT2d) + v.T.Subtract(&ZZ2, &TT2d) + return v +} + +func (v *projP1xP1) Sub(p *Point, q *projCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, ZZ2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YminusX) // flipped sign + MM.Multiply(&YminusX, &q.YplusX) // flipped sign + TT2d.Multiply(&p.t, &q.T2d) + ZZ2.Multiply(&p.z, &q.Z) + + ZZ2.Add(&ZZ2, &ZZ2) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Subtract(&ZZ2, &TT2d) // flipped sign + v.T.Add(&ZZ2, &TT2d) // flipped sign + return v +} + +func (v *projP1xP1) AddAffine(p *Point, q *affineCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YplusX) + MM.Multiply(&YminusX, &q.YminusX) + TT2d.Multiply(&p.t, &q.T2d) + + Z2.Add(&p.z, &p.z) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Add(&Z2, &TT2d) + v.T.Subtract(&Z2, &TT2d) + return v +} + +func (v *projP1xP1) SubAffine(p *Point, q *affineCached) *projP1xP1 { + var YplusX, YminusX, PP, MM, TT2d, Z2 field.Element + + YplusX.Add(&p.y, &p.x) + YminusX.Subtract(&p.y, &p.x) + + PP.Multiply(&YplusX, &q.YminusX) // flipped sign + MM.Multiply(&YminusX, &q.YplusX) // flipped sign + TT2d.Multiply(&p.t, &q.T2d) + + Z2.Add(&p.z, &p.z) + + v.X.Subtract(&PP, &MM) + v.Y.Add(&PP, &MM) + v.Z.Subtract(&Z2, &TT2d) // flipped sign + v.T.Add(&Z2, &TT2d) // flipped sign + return v +} + +// Doubling. + +func (v *projP1xP1) Double(p *projP2) *projP1xP1 { + var XX, YY, ZZ2, XplusYsq field.Element + + XX.Square(&p.X) + YY.Square(&p.Y) + ZZ2.Square(&p.Z) + ZZ2.Add(&ZZ2, &ZZ2) + XplusYsq.Add(&p.X, &p.Y) + XplusYsq.Square(&XplusYsq) + + v.Y.Add(&YY, &XX) + v.Z.Subtract(&YY, &XX) + + v.X.Subtract(&XplusYsq, &v.Y) + v.T.Subtract(&ZZ2, &v.Z) + return v +} + +// Negation. + +// Negate sets v = -p, and returns v. +func (v *Point) Negate(p *Point) *Point { + checkInitialized(p) + v.x.Negate(&p.x) + v.y.Set(&p.y) + v.z.Set(&p.z) + v.t.Negate(&p.t) + return v +} + +// Equal returns 1 if v is equivalent to u, and 0 otherwise. +func (v *Point) Equal(u *Point) int { + checkInitialized(v, u) + + var t1, t2, t3, t4 field.Element + t1.Multiply(&v.x, &u.z) + t2.Multiply(&u.x, &v.z) + t3.Multiply(&v.y, &u.z) + t4.Multiply(&u.y, &v.z) + + return t1.Equal(&t2) & t3.Equal(&t4) +} + +// Constant-time operations + +// Select sets v to a if cond == 1 and to b if cond == 0. +func (v *projCached) Select(a, b *projCached, cond int) *projCached { + v.YplusX.Select(&a.YplusX, &b.YplusX, cond) + v.YminusX.Select(&a.YminusX, &b.YminusX, cond) + v.Z.Select(&a.Z, &b.Z, cond) + v.T2d.Select(&a.T2d, &b.T2d, cond) + return v +} + +// Select sets v to a if cond == 1 and to b if cond == 0. +func (v *affineCached) Select(a, b *affineCached, cond int) *affineCached { + v.YplusX.Select(&a.YplusX, &b.YplusX, cond) + v.YminusX.Select(&a.YminusX, &b.YminusX, cond) + v.T2d.Select(&a.T2d, &b.T2d, cond) + return v +} + +// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. +func (v *projCached) CondNeg(cond int) *projCached { + v.YplusX.Swap(&v.YminusX, cond) + v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond) + return v +} + +// CondNeg negates v if cond == 1 and leaves it unchanged if cond == 0. +func (v *affineCached) CondNeg(cond int) *affineCached { + v.YplusX.Swap(&v.YminusX, cond) + v.T2d.Select(new(field.Element).Negate(&v.T2d), &v.T2d, cond) + return v +} diff --git a/vendor/filippo.io/edwards25519/extra.go b/vendor/filippo.io/edwards25519/extra.go new file mode 100644 index 00000000..d152d68f --- /dev/null +++ b/vendor/filippo.io/edwards25519/extra.go @@ -0,0 +1,349 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +// This file contains additional functionality that is not included in the +// upstream crypto/internal/edwards25519 package. + +import ( + "errors" + + "filippo.io/edwards25519/field" +) + +// ExtendedCoordinates returns v in extended coordinates (X:Y:Z:T) where +// x = X/Z, y = Y/Z, and xy = T/Z as in https://eprint.iacr.org/2008/522. +func (v *Point) ExtendedCoordinates() (X, Y, Z, T *field.Element) { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. Don't change the style without making + // sure it doesn't increase the inliner cost. + var e [4]field.Element + X, Y, Z, T = v.extendedCoordinates(&e) + return +} + +func (v *Point) extendedCoordinates(e *[4]field.Element) (X, Y, Z, T *field.Element) { + checkInitialized(v) + X = e[0].Set(&v.x) + Y = e[1].Set(&v.y) + Z = e[2].Set(&v.z) + T = e[3].Set(&v.t) + return +} + +// SetExtendedCoordinates sets v = (X:Y:Z:T) in extended coordinates where +// x = X/Z, y = Y/Z, and xy = T/Z as in https://eprint.iacr.org/2008/522. +// +// If the coordinates are invalid or don't represent a valid point on the curve, +// SetExtendedCoordinates returns nil and an error and the receiver is +// unchanged. Otherwise, SetExtendedCoordinates returns v. +func (v *Point) SetExtendedCoordinates(X, Y, Z, T *field.Element) (*Point, error) { + if !isOnCurve(X, Y, Z, T) { + return nil, errors.New("edwards25519: invalid point coordinates") + } + v.x.Set(X) + v.y.Set(Y) + v.z.Set(Z) + v.t.Set(T) + return v, nil +} + +func isOnCurve(X, Y, Z, T *field.Element) bool { + var lhs, rhs field.Element + XX := new(field.Element).Square(X) + YY := new(field.Element).Square(Y) + ZZ := new(field.Element).Square(Z) + TT := new(field.Element).Square(T) + // -x² + y² = 1 + dx²y² + // -(X/Z)² + (Y/Z)² = 1 + d(T/Z)² + // -X² + Y² = Z² + dT² + lhs.Subtract(YY, XX) + rhs.Multiply(d, TT).Add(&rhs, ZZ) + if lhs.Equal(&rhs) != 1 { + return false + } + // xy = T/Z + // XY/Z² = T/Z + // XY = TZ + lhs.Multiply(X, Y) + rhs.Multiply(T, Z) + return lhs.Equal(&rhs) == 1 +} + +// BytesMontgomery converts v to a point on the birationally-equivalent +// Curve25519 Montgomery curve, and returns its canonical 32 bytes encoding +// according to RFC 7748. +// +// Note that BytesMontgomery only encodes the u-coordinate, so v and -v encode +// to the same value. If v is the identity point, BytesMontgomery returns 32 +// zero bytes, analogously to the X25519 function. +// +// The lack of an inverse operation (such as SetMontgomeryBytes) is deliberate: +// while every valid edwards25519 point has a unique u-coordinate Montgomery +// encoding, X25519 accepts inputs on the quadratic twist, which don't correspond +// to any edwards25519 point, and every other X25519 input corresponds to two +// edwards25519 points. +func (v *Point) BytesMontgomery() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var buf [32]byte + return v.bytesMontgomery(&buf) +} + +func (v *Point) bytesMontgomery(buf *[32]byte) []byte { + checkInitialized(v) + + // RFC 7748, Section 4.1 provides the bilinear map to calculate the + // Montgomery u-coordinate + // + // u = (1 + y) / (1 - y) + // + // where y = Y / Z. + + var y, recip, u field.Element + + y.Multiply(&v.y, y.Invert(&v.z)) // y = Y / Z + recip.Invert(recip.Subtract(feOne, &y)) // r = 1/(1 - y) + u.Multiply(u.Add(feOne, &y), &recip) // u = (1 + y)*r + + return copyFieldElement(buf, &u) +} + +// MultByCofactor sets v = 8 * p, and returns v. +func (v *Point) MultByCofactor(p *Point) *Point { + checkInitialized(p) + result := projP1xP1{} + pp := (&projP2{}).FromP3(p) + result.Double(pp) + pp.FromP1xP1(&result) + result.Double(pp) + pp.FromP1xP1(&result) + result.Double(pp) + return v.fromP1xP1(&result) +} + +// Given k > 0, set s = s**(2*i). +func (s *Scalar) pow2k(k int) { + for i := 0; i < k; i++ { + s.Multiply(s, s) + } +} + +// Invert sets s to the inverse of a nonzero scalar v, and returns s. +// +// If t is zero, Invert returns zero. +func (s *Scalar) Invert(t *Scalar) *Scalar { + // Uses a hardcoded sliding window of width 4. + var table [8]Scalar + var tt Scalar + tt.Multiply(t, t) + table[0] = *t + for i := 0; i < 7; i++ { + table[i+1].Multiply(&table[i], &tt) + } + // Now table = [t**1, t**3, t**5, t**7, t**9, t**11, t**13, t**15] + // so t**k = t[k/2] for odd k + + // To compute the sliding window digits, use the following Sage script: + + // sage: import itertools + // sage: def sliding_window(w,k): + // ....: digits = [] + // ....: while k > 0: + // ....: if k % 2 == 1: + // ....: kmod = k % (2**w) + // ....: digits.append(kmod) + // ....: k = k - kmod + // ....: else: + // ....: digits.append(0) + // ....: k = k // 2 + // ....: return digits + + // Now we can compute s roughly as follows: + + // sage: s = 1 + // sage: for coeff in reversed(sliding_window(4,l-2)): + // ....: s = s*s + // ....: if coeff > 0 : + // ....: s = s*t**coeff + + // This works on one bit at a time, with many runs of zeros. + // The digits can be collapsed into [(count, coeff)] as follows: + + // sage: [(len(list(group)),d) for d,group in itertools.groupby(sliding_window(4,l-2))] + + // Entries of the form (k, 0) turn into pow2k(k) + // Entries of the form (1, coeff) turn into a squaring and then a table lookup. + // We can fold the squaring into the previous pow2k(k) as pow2k(k+1). + + *s = table[1/2] + s.pow2k(127 + 1) + s.Multiply(s, &table[1/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[9/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[11/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[13/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[15/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[7/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[15/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[5/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[1/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[15/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[15/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[7/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[3/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[11/2]) + s.pow2k(5 + 1) + s.Multiply(s, &table[11/2]) + s.pow2k(9 + 1) + s.Multiply(s, &table[9/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[3/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[3/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[3/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[9/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[7/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[3/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[13/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[7/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[9/2]) + s.pow2k(3 + 1) + s.Multiply(s, &table[15/2]) + s.pow2k(4 + 1) + s.Multiply(s, &table[11/2]) + + return s +} + +// MultiScalarMult sets v = sum(scalars[i] * points[i]), and returns v. +// +// Execution time depends only on the lengths of the two slices, which must match. +func (v *Point) MultiScalarMult(scalars []*Scalar, points []*Point) *Point { + if len(scalars) != len(points) { + panic("edwards25519: called MultiScalarMult with different size inputs") + } + checkInitialized(points...) + + // Proceed as in the single-base case, but share doublings + // between each point in the multiscalar equation. + + // Build lookup tables for each point + tables := make([]projLookupTable, len(points)) + for i := range tables { + tables[i].FromP3(points[i]) + } + // Compute signed radix-16 digits for each scalar + digits := make([][64]int8, len(scalars)) + for i := range digits { + digits[i] = scalars[i].signedRadix16() + } + + // Unwrap first loop iteration to save computing 16*identity + multiple := &projCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + // Lookup-and-add the appropriate multiple of each input point + for j := range tables { + tables[j].SelectInto(multiple, digits[j][63]) + tmp1.Add(v, multiple) // tmp1 = v + x_(j,63)*Q in P1xP1 coords + v.fromP1xP1(tmp1) // update v + } + tmp2.FromP3(v) // set up tmp2 = v in P2 coords for next iteration + for i := 62; i >= 0; i-- { + tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords + v.fromP1xP1(tmp1) // v = 16*(prev) in P3 coords + // Lookup-and-add the appropriate multiple of each input point + for j := range tables { + tables[j].SelectInto(multiple, digits[j][i]) + tmp1.Add(v, multiple) // tmp1 = v + x_(j,i)*Q in P1xP1 coords + v.fromP1xP1(tmp1) // update v + } + tmp2.FromP3(v) // set up tmp2 = v in P2 coords for next iteration + } + return v +} + +// VarTimeMultiScalarMult sets v = sum(scalars[i] * points[i]), and returns v. +// +// Execution time depends on the inputs. +func (v *Point) VarTimeMultiScalarMult(scalars []*Scalar, points []*Point) *Point { + if len(scalars) != len(points) { + panic("edwards25519: called VarTimeMultiScalarMult with different size inputs") + } + checkInitialized(points...) + + // Generalize double-base NAF computation to arbitrary sizes. + // Here all the points are dynamic, so we only use the smaller + // tables. + + // Build lookup tables for each point + tables := make([]nafLookupTable5, len(points)) + for i := range tables { + tables[i].FromP3(points[i]) + } + // Compute a NAF for each scalar + nafs := make([][256]int8, len(scalars)) + for i := range nafs { + nafs[i] = scalars[i].nonAdjacentForm(5) + } + + multiple := &projCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + tmp2.Zero() + + // Move from high to low bits, doubling the accumulator + // at each iteration and checking whether there is a nonzero + // coefficient to look up a multiple of. + // + // Skip trying to find the first nonzero coefficent, because + // searching might be more work than a few extra doublings. + for i := 255; i >= 0; i-- { + tmp1.Double(tmp2) + + for j := range nafs { + if nafs[j][i] > 0 { + v.fromP1xP1(tmp1) + tables[j].SelectInto(multiple, nafs[j][i]) + tmp1.Add(v, multiple) + } else if nafs[j][i] < 0 { + v.fromP1xP1(tmp1) + tables[j].SelectInto(multiple, -nafs[j][i]) + tmp1.Sub(v, multiple) + } + } + + tmp2.FromP1xP1(tmp1) + } + + v.fromP2(tmp2) + return v +} diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go b/vendor/filippo.io/edwards25519/field/fe.go similarity index 90% rename from vendor/golang.org/x/crypto/curve25519/internal/field/fe.go rename to vendor/filippo.io/edwards25519/field/fe.go index ca841ad9..5518ef2b 100644 --- a/vendor/golang.org/x/crypto/curve25519/internal/field/fe.go +++ b/vendor/filippo.io/edwards25519/field/fe.go @@ -8,6 +8,7 @@ package field import ( "crypto/subtle" "encoding/binary" + "errors" "math/bits" ) @@ -92,7 +93,7 @@ func (v *Element) Add(a, b *Element) *Element { // Using the generic implementation here is actually faster than the // assembly. Probably because the body of this function is so simple that // the compiler can figure out better optimizations by inlining the carry - // propagation. TODO + // propagation. return v.carryPropagateGeneric() } @@ -186,14 +187,17 @@ func (v *Element) Set(a *Element) *Element { return v } -// SetBytes sets v to x, which must be a 32-byte little-endian encoding. +// SetBytes sets v to x, where x is a 32-byte little-endian encoding. If x is +// not of the right length, SetBytes returns nil and an error, and the +// receiver is unchanged. // // Consistent with RFC 7748, the most significant bit (the high bit of the // last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1) -// are accepted. Note that this is laxer than specified by RFC 8032. -func (v *Element) SetBytes(x []byte) *Element { +// are accepted. Note that this is laxer than specified by RFC 8032, but +// consistent with most Ed25519 implementations. +func (v *Element) SetBytes(x []byte) (*Element, error) { if len(x) != 32 { - panic("edwards25519: invalid field element input size") + return nil, errors.New("edwards25519: invalid field element input size") } // Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51). @@ -208,12 +212,12 @@ func (v *Element) SetBytes(x []byte) *Element { // Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51). v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1 v.l3 &= maskLow51Bits - // Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51). + // Bits 204:255 (bytes 24:32, bits 192:256, shift 12, mask 51). // Note: not bytes 25:33, shift 4, to avoid overread. v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12 v.l4 &= maskLow51Bits - return v + return v, nil } // Bytes returns the canonical 32-byte little-endian encoding of v. @@ -391,26 +395,26 @@ var sqrtM1 = &Element{1718705420411056, 234908883556509, // If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio // sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00, // and returns r and 0. -func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) { - var a, b Element +func (r *Element) SqrtRatio(u, v *Element) (R *Element, wasSquare int) { + t0 := new(Element) // r = (u * v3) * (u * v7)^((p-5)/8) - v2 := a.Square(v) - uv3 := b.Multiply(u, b.Multiply(v2, v)) - uv7 := a.Multiply(uv3, a.Square(v2)) - r.Multiply(uv3, r.Pow22523(uv7)) + v2 := new(Element).Square(v) + uv3 := new(Element).Multiply(u, t0.Multiply(v2, v)) + uv7 := new(Element).Multiply(uv3, t0.Square(v2)) + rr := new(Element).Multiply(uv3, t0.Pow22523(uv7)) - check := a.Multiply(v, a.Square(r)) // check = v * r^2 + check := new(Element).Multiply(v, t0.Square(rr)) // check = v * r^2 - uNeg := b.Negate(u) + uNeg := new(Element).Negate(u) correctSignSqrt := check.Equal(u) flippedSignSqrt := check.Equal(uNeg) - flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1)) + flippedSignSqrtI := check.Equal(t0.Multiply(uNeg, sqrtM1)) - rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r + rPrime := new(Element).Multiply(rr, sqrtM1) // r_prime = SQRT_M1 * r // r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r) - r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI) + rr.Select(rPrime, rr, flippedSignSqrt|flippedSignSqrtI) - r.Absolute(r) // Choose the nonnegative square root. + r.Absolute(rr) // Choose the nonnegative square root. return r, correctSignSqrt | flippedSignSqrt } diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go b/vendor/filippo.io/edwards25519/field/fe_amd64.go similarity index 93% rename from vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go rename to vendor/filippo.io/edwards25519/field/fe_amd64.go index 70c54169..edcf163c 100644 --- a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go +++ b/vendor/filippo.io/edwards25519/field/fe_amd64.go @@ -1,6 +1,7 @@ // Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. //go:build amd64 && gc && !purego +// +build amd64,gc,!purego package field diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s b/vendor/filippo.io/edwards25519/field/fe_amd64.s similarity index 99% rename from vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s rename to vendor/filippo.io/edwards25519/field/fe_amd64.s index 60817acc..293f013c 100644 --- a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.s +++ b/vendor/filippo.io/edwards25519/field/fe_amd64.s @@ -1,6 +1,7 @@ // Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT. //go:build amd64 && gc && !purego +// +build amd64,gc,!purego #include "textflag.h" diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go b/vendor/filippo.io/edwards25519/field/fe_amd64_noasm.go similarity index 92% rename from vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go rename to vendor/filippo.io/edwards25519/field/fe_amd64_noasm.go index 9da280d1..ddb6c9b8 100644 --- a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go +++ b/vendor/filippo.io/edwards25519/field/fe_amd64_noasm.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. //go:build !amd64 || !gc || purego +// +build !amd64 !gc purego package field diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go b/vendor/filippo.io/edwards25519/field/fe_arm64.go similarity index 92% rename from vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go rename to vendor/filippo.io/edwards25519/field/fe_arm64.go index 075fe9b9..af459ef5 100644 --- a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go +++ b/vendor/filippo.io/edwards25519/field/fe_arm64.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. //go:build arm64 && gc && !purego +// +build arm64,gc,!purego package field diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s b/vendor/filippo.io/edwards25519/field/fe_arm64.s similarity index 100% rename from vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.s rename to vendor/filippo.io/edwards25519/field/fe_arm64.s diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go b/vendor/filippo.io/edwards25519/field/fe_arm64_noasm.go similarity index 91% rename from vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go rename to vendor/filippo.io/edwards25519/field/fe_arm64_noasm.go index fc029ac1..234a5b2e 100644 --- a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go +++ b/vendor/filippo.io/edwards25519/field/fe_arm64_noasm.go @@ -3,6 +3,7 @@ // license that can be found in the LICENSE file. //go:build !arm64 || !gc || purego +// +build !arm64 !gc purego package field diff --git a/vendor/filippo.io/edwards25519/field/fe_extra.go b/vendor/filippo.io/edwards25519/field/fe_extra.go new file mode 100644 index 00000000..1ef503b9 --- /dev/null +++ b/vendor/filippo.io/edwards25519/field/fe_extra.go @@ -0,0 +1,50 @@ +// Copyright (c) 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package field + +import "errors" + +// This file contains additional functionality that is not included in the +// upstream crypto/ed25519/edwards25519/field package. + +// SetWideBytes sets v to x, where x is a 64-byte little-endian encoding, which +// is reduced modulo the field order. If x is not of the right length, +// SetWideBytes returns nil and an error, and the receiver is unchanged. +// +// SetWideBytes is not necessary to select a uniformly distributed value, and is +// only provided for compatibility: SetBytes can be used instead as the chance +// of bias is less than 2⁻²⁵⁰. +func (v *Element) SetWideBytes(x []byte) (*Element, error) { + if len(x) != 64 { + return nil, errors.New("edwards25519: invalid SetWideBytes input size") + } + + // Split the 64 bytes into two elements, and extract the most significant + // bit of each, which is ignored by SetBytes. + lo, _ := new(Element).SetBytes(x[:32]) + loMSB := uint64(x[31] >> 7) + hi, _ := new(Element).SetBytes(x[32:]) + hiMSB := uint64(x[63] >> 7) + + // The output we want is + // + // v = lo + loMSB * 2²⁵⁵ + hi * 2²⁵⁶ + hiMSB * 2⁵¹¹ + // + // which applying the reduction identity comes out to + // + // v = lo + loMSB * 19 + hi * 2 * 19 + hiMSB * 2 * 19² + // + // l0 will be the sum of a 52 bits value (lo.l0), plus a 5 bits value + // (loMSB * 19), a 6 bits value (hi.l0 * 2 * 19), and a 10 bits value + // (hiMSB * 2 * 19²), so it fits in a uint64. + + v.l0 = lo.l0 + loMSB*19 + hi.l0*2*19 + hiMSB*2*19*19 + v.l1 = lo.l1 + hi.l1*2*19 + v.l2 = lo.l2 + hi.l2*2*19 + v.l3 = lo.l3 + hi.l3*2*19 + v.l4 = lo.l4 + hi.l4*2*19 + + return v.carryPropagate(), nil +} diff --git a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go b/vendor/filippo.io/edwards25519/field/fe_generic.go similarity index 96% rename from vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go rename to vendor/filippo.io/edwards25519/field/fe_generic.go index 2671217d..86f5fd95 100644 --- a/vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go +++ b/vendor/filippo.io/edwards25519/field/fe_generic.go @@ -156,7 +156,7 @@ func feMulGeneric(v, a, b *Element) { rr4 := r4.lo&maskLow51Bits + c3 // Now all coefficients fit into 64-bit registers but are still too large to - // be passed around as a Element. We therefore do one last carry chain, + // be passed around as an Element. We therefore do one last carry chain, // where the carries will be small enough to fit in the wiggle room above 2⁵¹. *v = Element{rr0, rr1, rr2, rr3, rr4} v.carryPropagate() @@ -246,7 +246,7 @@ func feSquareGeneric(v, a *Element) { } // carryPropagateGeneric brings the limbs below 52 bits by applying the reduction -// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. TODO inline +// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. func (v *Element) carryPropagateGeneric() *Element { c0 := v.l0 >> 51 c1 := v.l1 >> 51 @@ -254,6 +254,8 @@ func (v *Element) carryPropagateGeneric() *Element { c3 := v.l3 >> 51 c4 := v.l4 >> 51 + // c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and + // the final l0 will be at most 52 bits. Similarly for the rest. v.l0 = v.l0&maskLow51Bits + c4*19 v.l1 = v.l1&maskLow51Bits + c0 v.l2 = v.l2&maskLow51Bits + c1 diff --git a/vendor/filippo.io/edwards25519/scalar.go b/vendor/filippo.io/edwards25519/scalar.go new file mode 100644 index 00000000..3fd16538 --- /dev/null +++ b/vendor/filippo.io/edwards25519/scalar.go @@ -0,0 +1,343 @@ +// Copyright (c) 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package edwards25519 + +import ( + "encoding/binary" + "errors" +) + +// A Scalar is an integer modulo +// +// l = 2^252 + 27742317777372353535851937790883648493 +// +// which is the prime order of the edwards25519 group. +// +// This type works similarly to math/big.Int, and all arguments and +// receivers are allowed to alias. +// +// The zero value is a valid zero element. +type Scalar struct { + // s is the scalar in the Montgomery domain, in the format of the + // fiat-crypto implementation. + s fiatScalarMontgomeryDomainFieldElement +} + +// The field implementation in scalar_fiat.go is generated by the fiat-crypto +// project (https://github.com/mit-plv/fiat-crypto) at version v0.0.9 (23d2dbc) +// from a formally verified model. +// +// fiat-crypto code comes under the following license. +// +// Copyright (c) 2015-2020 The fiat-crypto Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// THIS SOFTWARE IS PROVIDED BY the fiat-crypto authors "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 Berkeley Software Design, +// Inc. 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. +// + +// NewScalar returns a new zero Scalar. +func NewScalar() *Scalar { + return &Scalar{} +} + +// MultiplyAdd sets s = x * y + z mod l, and returns s. It is equivalent to +// using Multiply and then Add. +func (s *Scalar) MultiplyAdd(x, y, z *Scalar) *Scalar { + // Make a copy of z in case it aliases s. + zCopy := new(Scalar).Set(z) + return s.Multiply(x, y).Add(s, zCopy) +} + +// Add sets s = x + y mod l, and returns s. +func (s *Scalar) Add(x, y *Scalar) *Scalar { + // s = 1 * x + y mod l + fiatScalarAdd(&s.s, &x.s, &y.s) + return s +} + +// Subtract sets s = x - y mod l, and returns s. +func (s *Scalar) Subtract(x, y *Scalar) *Scalar { + // s = -1 * y + x mod l + fiatScalarSub(&s.s, &x.s, &y.s) + return s +} + +// Negate sets s = -x mod l, and returns s. +func (s *Scalar) Negate(x *Scalar) *Scalar { + // s = -1 * x + 0 mod l + fiatScalarOpp(&s.s, &x.s) + return s +} + +// Multiply sets s = x * y mod l, and returns s. +func (s *Scalar) Multiply(x, y *Scalar) *Scalar { + // s = x * y + 0 mod l + fiatScalarMul(&s.s, &x.s, &y.s) + return s +} + +// Set sets s = x, and returns s. +func (s *Scalar) Set(x *Scalar) *Scalar { + *s = *x + return s +} + +// SetUniformBytes sets s = x mod l, where x is a 64-byte little-endian integer. +// If x is not of the right length, SetUniformBytes returns nil and an error, +// and the receiver is unchanged. +// +// SetUniformBytes can be used to set s to a uniformly distributed value given +// 64 uniformly distributed random bytes. +func (s *Scalar) SetUniformBytes(x []byte) (*Scalar, error) { + if len(x) != 64 { + return nil, errors.New("edwards25519: invalid SetUniformBytes input length") + } + + // We have a value x of 512 bits, but our fiatScalarFromBytes function + // expects an input lower than l, which is a little over 252 bits. + // + // Instead of writing a reduction function that operates on wider inputs, we + // can interpret x as the sum of three shorter values a, b, and c. + // + // x = a + b * 2^168 + c * 2^336 mod l + // + // We then precompute 2^168 and 2^336 modulo l, and perform the reduction + // with two multiplications and two additions. + + s.setShortBytes(x[:21]) + t := new(Scalar).setShortBytes(x[21:42]) + s.Add(s, t.Multiply(t, scalarTwo168)) + t.setShortBytes(x[42:]) + s.Add(s, t.Multiply(t, scalarTwo336)) + + return s, nil +} + +// scalarTwo168 and scalarTwo336 are 2^168 and 2^336 modulo l, encoded as a +// fiatScalarMontgomeryDomainFieldElement, which is a little-endian 4-limb value +// in the 2^256 Montgomery domain. +var scalarTwo168 = &Scalar{s: [4]uint64{0x5b8ab432eac74798, 0x38afddd6de59d5d7, + 0xa2c131b399411b7c, 0x6329a7ed9ce5a30}} +var scalarTwo336 = &Scalar{s: [4]uint64{0xbd3d108e2b35ecc5, 0x5c3a3718bdf9c90b, + 0x63aa97a331b4f2ee, 0x3d217f5be65cb5c}} + +// setShortBytes sets s = x mod l, where x is a little-endian integer shorter +// than 32 bytes. +func (s *Scalar) setShortBytes(x []byte) *Scalar { + if len(x) >= 32 { + panic("edwards25519: internal error: setShortBytes called with a long string") + } + var buf [32]byte + copy(buf[:], x) + fiatScalarFromBytes((*[4]uint64)(&s.s), &buf) + fiatScalarToMontgomery(&s.s, (*fiatScalarNonMontgomeryDomainFieldElement)(&s.s)) + return s +} + +// SetCanonicalBytes sets s = x, where x is a 32-byte little-endian encoding of +// s, and returns s. If x is not a canonical encoding of s, SetCanonicalBytes +// returns nil and an error, and the receiver is unchanged. +func (s *Scalar) SetCanonicalBytes(x []byte) (*Scalar, error) { + if len(x) != 32 { + return nil, errors.New("invalid scalar length") + } + if !isReduced(x) { + return nil, errors.New("invalid scalar encoding") + } + + fiatScalarFromBytes((*[4]uint64)(&s.s), (*[32]byte)(x)) + fiatScalarToMontgomery(&s.s, (*fiatScalarNonMontgomeryDomainFieldElement)(&s.s)) + + return s, nil +} + +// scalarMinusOneBytes is l - 1 in little endian. +var scalarMinusOneBytes = [32]byte{236, 211, 245, 92, 26, 99, 18, 88, 214, 156, 247, 162, 222, 249, 222, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16} + +// isReduced returns whether the given scalar in 32-byte little endian encoded +// form is reduced modulo l. +func isReduced(s []byte) bool { + if len(s) != 32 { + return false + } + + for i := len(s) - 1; i >= 0; i-- { + switch { + case s[i] > scalarMinusOneBytes[i]: + return false + case s[i] < scalarMinusOneBytes[i]: + return true + } + } + return true +} + +// SetBytesWithClamping applies the buffer pruning described in RFC 8032, +// Section 5.1.5 (also known as clamping) and sets s to the result. The input +// must be 32 bytes, and it is not modified. If x is not of the right length, +// SetBytesWithClamping returns nil and an error, and the receiver is unchanged. +// +// Note that since Scalar values are always reduced modulo the prime order of +// the curve, the resulting value will not preserve any of the cofactor-clearing +// properties that clamping is meant to provide. It will however work as +// expected as long as it is applied to points on the prime order subgroup, like +// in Ed25519. In fact, it is lost to history why RFC 8032 adopted the +// irrelevant RFC 7748 clamping, but it is now required for compatibility. +func (s *Scalar) SetBytesWithClamping(x []byte) (*Scalar, error) { + // The description above omits the purpose of the high bits of the clamping + // for brevity, but those are also lost to reductions, and are also + // irrelevant to edwards25519 as they protect against a specific + // implementation bug that was once observed in a generic Montgomery ladder. + if len(x) != 32 { + return nil, errors.New("edwards25519: invalid SetBytesWithClamping input length") + } + + // We need to use the wide reduction from SetUniformBytes, since clamping + // sets the 2^254 bit, making the value higher than the order. + var wideBytes [64]byte + copy(wideBytes[:], x[:]) + wideBytes[0] &= 248 + wideBytes[31] &= 63 + wideBytes[31] |= 64 + return s.SetUniformBytes(wideBytes[:]) +} + +// Bytes returns the canonical 32-byte little-endian encoding of s. +func (s *Scalar) Bytes() []byte { + // This function is outlined to make the allocations inline in the caller + // rather than happen on the heap. + var encoded [32]byte + return s.bytes(&encoded) +} + +func (s *Scalar) bytes(out *[32]byte) []byte { + var ss fiatScalarNonMontgomeryDomainFieldElement + fiatScalarFromMontgomery(&ss, &s.s) + fiatScalarToBytes(out, (*[4]uint64)(&ss)) + return out[:] +} + +// Equal returns 1 if s and t are equal, and 0 otherwise. +func (s *Scalar) Equal(t *Scalar) int { + var diff fiatScalarMontgomeryDomainFieldElement + fiatScalarSub(&diff, &s.s, &t.s) + var nonzero uint64 + fiatScalarNonzero(&nonzero, (*[4]uint64)(&diff)) + nonzero |= nonzero >> 32 + nonzero |= nonzero >> 16 + nonzero |= nonzero >> 8 + nonzero |= nonzero >> 4 + nonzero |= nonzero >> 2 + nonzero |= nonzero >> 1 + return int(^nonzero) & 1 +} + +// nonAdjacentForm computes a width-w non-adjacent form for this scalar. +// +// w must be between 2 and 8, or nonAdjacentForm will panic. +func (s *Scalar) nonAdjacentForm(w uint) [256]int8 { + // This implementation is adapted from the one + // in curve25519-dalek and is documented there: + // https://github.com/dalek-cryptography/curve25519-dalek/blob/f630041af28e9a405255f98a8a93adca18e4315b/src/scalar.rs#L800-L871 + b := s.Bytes() + if b[31] > 127 { + panic("scalar has high bit set illegally") + } + if w < 2 { + panic("w must be at least 2 by the definition of NAF") + } else if w > 8 { + panic("NAF digits must fit in int8") + } + + var naf [256]int8 + var digits [5]uint64 + + for i := 0; i < 4; i++ { + digits[i] = binary.LittleEndian.Uint64(b[i*8:]) + } + + width := uint64(1 << w) + windowMask := uint64(width - 1) + + pos := uint(0) + carry := uint64(0) + for pos < 256 { + indexU64 := pos / 64 + indexBit := pos % 64 + var bitBuf uint64 + if indexBit < 64-w { + // This window's bits are contained in a single u64 + bitBuf = digits[indexU64] >> indexBit + } else { + // Combine the current 64 bits with bits from the next 64 + bitBuf = (digits[indexU64] >> indexBit) | (digits[1+indexU64] << (64 - indexBit)) + } + + // Add carry into the current window + window := carry + (bitBuf & windowMask) + + if window&1 == 0 { + // If the window value is even, preserve the carry and continue. + // Why is the carry preserved? + // If carry == 0 and window & 1 == 0, + // then the next carry should be 0 + // If carry == 1 and window & 1 == 0, + // then bit_buf & 1 == 1 so the next carry should be 1 + pos += 1 + continue + } + + if window < width/2 { + carry = 0 + naf[pos] = int8(window) + } else { + carry = 1 + naf[pos] = int8(window) - int8(width) + } + + pos += w + } + return naf +} + +func (s *Scalar) signedRadix16() [64]int8 { + b := s.Bytes() + if b[31] > 127 { + panic("scalar has high bit set illegally") + } + + var digits [64]int8 + + // Compute unsigned radix-16 digits: + for i := 0; i < 32; i++ { + digits[2*i] = int8(b[i] & 15) + digits[2*i+1] = int8((b[i] >> 4) & 15) + } + + // Recenter coefficients: + for i := 0; i < 63; i++ { + carry := (digits[i] + 8) >> 4 + digits[i] -= carry << 4 + digits[i+1] += carry + } + + return digits +} diff --git a/vendor/filippo.io/edwards25519/scalar_fiat.go b/vendor/filippo.io/edwards25519/scalar_fiat.go new file mode 100644 index 00000000..2e5782b6 --- /dev/null +++ b/vendor/filippo.io/edwards25519/scalar_fiat.go @@ -0,0 +1,1147 @@ +// Code generated by Fiat Cryptography. DO NOT EDIT. +// +// Autogenerated: word_by_word_montgomery --lang Go --cmovznz-by-mul --relax-primitive-carry-to-bitwidth 32,64 --public-function-case camelCase --public-type-case camelCase --private-function-case camelCase --private-type-case camelCase --doc-text-before-function-name '' --doc-newline-before-package-declaration --doc-prepend-header 'Code generated by Fiat Cryptography. DO NOT EDIT.' --package-name edwards25519 Scalar 64 '2^252 + 27742317777372353535851937790883648493' mul add sub opp nonzero from_montgomery to_montgomery to_bytes from_bytes +// +// curve description: Scalar +// +// machine_wordsize = 64 (from "64") +// +// requested operations: mul, add, sub, opp, nonzero, from_montgomery, to_montgomery, to_bytes, from_bytes +// +// m = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed (from "2^252 + 27742317777372353535851937790883648493") +// +// +// +// NOTE: In addition to the bounds specified above each function, all +// +// functions synthesized for this Montgomery arithmetic require the +// +// input to be strictly less than the prime modulus (m), and also +// +// require the input to be in the unique saturated representation. +// +// All functions also ensure that these two properties are true of +// +// return values. +// +// +// +// Computed values: +// +// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) +// +// bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) +// +// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in +// +// if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 + +package edwards25519 + +import "math/bits" + +type fiatScalarUint1 uint64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 +type fiatScalarInt1 int64 // We use uint64 instead of a more narrow type for performance reasons; see https://github.com/mit-plv/fiat-crypto/pull/1006#issuecomment-892625927 + +// The type fiatScalarMontgomeryDomainFieldElement is a field element in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type fiatScalarMontgomeryDomainFieldElement [4]uint64 + +// The type fiatScalarNonMontgomeryDomainFieldElement is a field element NOT in the Montgomery domain. +// +// Bounds: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +type fiatScalarNonMontgomeryDomainFieldElement [4]uint64 + +// fiatScalarCmovznzU64 is a single-word conditional move. +// +// Postconditions: +// +// out1 = (if arg1 = 0 then arg2 else arg3) +// +// Input Bounds: +// +// arg1: [0x0 ~> 0x1] +// arg2: [0x0 ~> 0xffffffffffffffff] +// arg3: [0x0 ~> 0xffffffffffffffff] +// +// Output Bounds: +// +// out1: [0x0 ~> 0xffffffffffffffff] +func fiatScalarCmovznzU64(out1 *uint64, arg1 fiatScalarUint1, arg2 uint64, arg3 uint64) { + x1 := (uint64(arg1) * 0xffffffffffffffff) + x2 := ((x1 & arg3) | ((^x1) & arg2)) + *out1 = x2 +} + +// fiatScalarMul multiplies two field elements in the Montgomery domain. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// +// Postconditions: +// +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +func fiatScalarMul(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement, arg2 *fiatScalarMontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, arg2[3]) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, arg2[2]) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, arg2[1]) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, arg2[0]) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(x12, x9, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x10, x7, uint64(fiatScalarUint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(fiatScalarUint1(x16))) + x19 := (uint64(fiatScalarUint1(x18)) + x6) + var x20 uint64 + _, x20 = bits.Mul64(x11, 0xd2b51da312547e1b) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x20, 0x1000000000000000) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x20, 0x14def9dea2f79cd6) + var x26 uint64 + var x27 uint64 + x27, x26 = bits.Mul64(x20, 0x5812631a5cf5d3ed) + var x28 uint64 + var x29 uint64 + x28, x29 = bits.Add64(x27, x24, uint64(0x0)) + x30 := (uint64(fiatScalarUint1(x29)) + x25) + var x32 uint64 + _, x32 = bits.Add64(x11, x26, uint64(0x0)) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Add64(x13, x28, uint64(fiatScalarUint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x15, x30, uint64(fiatScalarUint1(x34))) + var x37 uint64 + var x38 uint64 + x37, x38 = bits.Add64(x17, x22, uint64(fiatScalarUint1(x36))) + var x39 uint64 + var x40 uint64 + x39, x40 = bits.Add64(x19, x23, uint64(fiatScalarUint1(x38))) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(x1, arg2[3]) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, arg2[2]) + var x45 uint64 + var x46 uint64 + x46, x45 = bits.Mul64(x1, arg2[1]) + var x47 uint64 + var x48 uint64 + x48, x47 = bits.Mul64(x1, arg2[0]) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(x48, x45, uint64(0x0)) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x46, x43, uint64(fiatScalarUint1(x50))) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x44, x41, uint64(fiatScalarUint1(x52))) + x55 := (uint64(fiatScalarUint1(x54)) + x42) + var x56 uint64 + var x57 uint64 + x56, x57 = bits.Add64(x33, x47, uint64(0x0)) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64(x35, x49, uint64(fiatScalarUint1(x57))) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x37, x51, uint64(fiatScalarUint1(x59))) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x39, x53, uint64(fiatScalarUint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(uint64(fiatScalarUint1(x40)), x55, uint64(fiatScalarUint1(x63))) + var x66 uint64 + _, x66 = bits.Mul64(x56, 0xd2b51da312547e1b) + var x68 uint64 + var x69 uint64 + x69, x68 = bits.Mul64(x66, 0x1000000000000000) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x66, 0x14def9dea2f79cd6) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x66, 0x5812631a5cf5d3ed) + var x74 uint64 + var x75 uint64 + x74, x75 = bits.Add64(x73, x70, uint64(0x0)) + x76 := (uint64(fiatScalarUint1(x75)) + x71) + var x78 uint64 + _, x78 = bits.Add64(x56, x72, uint64(0x0)) + var x79 uint64 + var x80 uint64 + x79, x80 = bits.Add64(x58, x74, uint64(fiatScalarUint1(x78))) + var x81 uint64 + var x82 uint64 + x81, x82 = bits.Add64(x60, x76, uint64(fiatScalarUint1(x80))) + var x83 uint64 + var x84 uint64 + x83, x84 = bits.Add64(x62, x68, uint64(fiatScalarUint1(x82))) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x64, x69, uint64(fiatScalarUint1(x84))) + x87 := (uint64(fiatScalarUint1(x86)) + uint64(fiatScalarUint1(x65))) + var x88 uint64 + var x89 uint64 + x89, x88 = bits.Mul64(x2, arg2[3]) + var x90 uint64 + var x91 uint64 + x91, x90 = bits.Mul64(x2, arg2[2]) + var x92 uint64 + var x93 uint64 + x93, x92 = bits.Mul64(x2, arg2[1]) + var x94 uint64 + var x95 uint64 + x95, x94 = bits.Mul64(x2, arg2[0]) + var x96 uint64 + var x97 uint64 + x96, x97 = bits.Add64(x95, x92, uint64(0x0)) + var x98 uint64 + var x99 uint64 + x98, x99 = bits.Add64(x93, x90, uint64(fiatScalarUint1(x97))) + var x100 uint64 + var x101 uint64 + x100, x101 = bits.Add64(x91, x88, uint64(fiatScalarUint1(x99))) + x102 := (uint64(fiatScalarUint1(x101)) + x89) + var x103 uint64 + var x104 uint64 + x103, x104 = bits.Add64(x79, x94, uint64(0x0)) + var x105 uint64 + var x106 uint64 + x105, x106 = bits.Add64(x81, x96, uint64(fiatScalarUint1(x104))) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x83, x98, uint64(fiatScalarUint1(x106))) + var x109 uint64 + var x110 uint64 + x109, x110 = bits.Add64(x85, x100, uint64(fiatScalarUint1(x108))) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x87, x102, uint64(fiatScalarUint1(x110))) + var x113 uint64 + _, x113 = bits.Mul64(x103, 0xd2b51da312547e1b) + var x115 uint64 + var x116 uint64 + x116, x115 = bits.Mul64(x113, 0x1000000000000000) + var x117 uint64 + var x118 uint64 + x118, x117 = bits.Mul64(x113, 0x14def9dea2f79cd6) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(x113, 0x5812631a5cf5d3ed) + var x121 uint64 + var x122 uint64 + x121, x122 = bits.Add64(x120, x117, uint64(0x0)) + x123 := (uint64(fiatScalarUint1(x122)) + x118) + var x125 uint64 + _, x125 = bits.Add64(x103, x119, uint64(0x0)) + var x126 uint64 + var x127 uint64 + x126, x127 = bits.Add64(x105, x121, uint64(fiatScalarUint1(x125))) + var x128 uint64 + var x129 uint64 + x128, x129 = bits.Add64(x107, x123, uint64(fiatScalarUint1(x127))) + var x130 uint64 + var x131 uint64 + x130, x131 = bits.Add64(x109, x115, uint64(fiatScalarUint1(x129))) + var x132 uint64 + var x133 uint64 + x132, x133 = bits.Add64(x111, x116, uint64(fiatScalarUint1(x131))) + x134 := (uint64(fiatScalarUint1(x133)) + uint64(fiatScalarUint1(x112))) + var x135 uint64 + var x136 uint64 + x136, x135 = bits.Mul64(x3, arg2[3]) + var x137 uint64 + var x138 uint64 + x138, x137 = bits.Mul64(x3, arg2[2]) + var x139 uint64 + var x140 uint64 + x140, x139 = bits.Mul64(x3, arg2[1]) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x3, arg2[0]) + var x143 uint64 + var x144 uint64 + x143, x144 = bits.Add64(x142, x139, uint64(0x0)) + var x145 uint64 + var x146 uint64 + x145, x146 = bits.Add64(x140, x137, uint64(fiatScalarUint1(x144))) + var x147 uint64 + var x148 uint64 + x147, x148 = bits.Add64(x138, x135, uint64(fiatScalarUint1(x146))) + x149 := (uint64(fiatScalarUint1(x148)) + x136) + var x150 uint64 + var x151 uint64 + x150, x151 = bits.Add64(x126, x141, uint64(0x0)) + var x152 uint64 + var x153 uint64 + x152, x153 = bits.Add64(x128, x143, uint64(fiatScalarUint1(x151))) + var x154 uint64 + var x155 uint64 + x154, x155 = bits.Add64(x130, x145, uint64(fiatScalarUint1(x153))) + var x156 uint64 + var x157 uint64 + x156, x157 = bits.Add64(x132, x147, uint64(fiatScalarUint1(x155))) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Add64(x134, x149, uint64(fiatScalarUint1(x157))) + var x160 uint64 + _, x160 = bits.Mul64(x150, 0xd2b51da312547e1b) + var x162 uint64 + var x163 uint64 + x163, x162 = bits.Mul64(x160, 0x1000000000000000) + var x164 uint64 + var x165 uint64 + x165, x164 = bits.Mul64(x160, 0x14def9dea2f79cd6) + var x166 uint64 + var x167 uint64 + x167, x166 = bits.Mul64(x160, 0x5812631a5cf5d3ed) + var x168 uint64 + var x169 uint64 + x168, x169 = bits.Add64(x167, x164, uint64(0x0)) + x170 := (uint64(fiatScalarUint1(x169)) + x165) + var x172 uint64 + _, x172 = bits.Add64(x150, x166, uint64(0x0)) + var x173 uint64 + var x174 uint64 + x173, x174 = bits.Add64(x152, x168, uint64(fiatScalarUint1(x172))) + var x175 uint64 + var x176 uint64 + x175, x176 = bits.Add64(x154, x170, uint64(fiatScalarUint1(x174))) + var x177 uint64 + var x178 uint64 + x177, x178 = bits.Add64(x156, x162, uint64(fiatScalarUint1(x176))) + var x179 uint64 + var x180 uint64 + x179, x180 = bits.Add64(x158, x163, uint64(fiatScalarUint1(x178))) + x181 := (uint64(fiatScalarUint1(x180)) + uint64(fiatScalarUint1(x159))) + var x182 uint64 + var x183 uint64 + x182, x183 = bits.Sub64(x173, 0x5812631a5cf5d3ed, uint64(0x0)) + var x184 uint64 + var x185 uint64 + x184, x185 = bits.Sub64(x175, 0x14def9dea2f79cd6, uint64(fiatScalarUint1(x183))) + var x186 uint64 + var x187 uint64 + x186, x187 = bits.Sub64(x177, uint64(0x0), uint64(fiatScalarUint1(x185))) + var x188 uint64 + var x189 uint64 + x188, x189 = bits.Sub64(x179, 0x1000000000000000, uint64(fiatScalarUint1(x187))) + var x191 uint64 + _, x191 = bits.Sub64(x181, uint64(0x0), uint64(fiatScalarUint1(x189))) + var x192 uint64 + fiatScalarCmovznzU64(&x192, fiatScalarUint1(x191), x182, x173) + var x193 uint64 + fiatScalarCmovznzU64(&x193, fiatScalarUint1(x191), x184, x175) + var x194 uint64 + fiatScalarCmovznzU64(&x194, fiatScalarUint1(x191), x186, x177) + var x195 uint64 + fiatScalarCmovznzU64(&x195, fiatScalarUint1(x191), x188, x179) + out1[0] = x192 + out1[1] = x193 + out1[2] = x194 + out1[3] = x195 +} + +// fiatScalarAdd adds two field elements in the Montgomery domain. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// +// Postconditions: +// +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +func fiatScalarAdd(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement, arg2 *fiatScalarMontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Add64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Add64(arg1[1], arg2[1], uint64(fiatScalarUint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Add64(arg1[2], arg2[2], uint64(fiatScalarUint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Add64(arg1[3], arg2[3], uint64(fiatScalarUint1(x6))) + var x9 uint64 + var x10 uint64 + x9, x10 = bits.Sub64(x1, 0x5812631a5cf5d3ed, uint64(0x0)) + var x11 uint64 + var x12 uint64 + x11, x12 = bits.Sub64(x3, 0x14def9dea2f79cd6, uint64(fiatScalarUint1(x10))) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Sub64(x5, uint64(0x0), uint64(fiatScalarUint1(x12))) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Sub64(x7, 0x1000000000000000, uint64(fiatScalarUint1(x14))) + var x18 uint64 + _, x18 = bits.Sub64(uint64(fiatScalarUint1(x8)), uint64(0x0), uint64(fiatScalarUint1(x16))) + var x19 uint64 + fiatScalarCmovznzU64(&x19, fiatScalarUint1(x18), x9, x1) + var x20 uint64 + fiatScalarCmovznzU64(&x20, fiatScalarUint1(x18), x11, x3) + var x21 uint64 + fiatScalarCmovznzU64(&x21, fiatScalarUint1(x18), x13, x5) + var x22 uint64 + fiatScalarCmovznzU64(&x22, fiatScalarUint1(x18), x15, x7) + out1[0] = x19 + out1[1] = x20 + out1[2] = x21 + out1[3] = x22 +} + +// fiatScalarSub subtracts two field elements in the Montgomery domain. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// 0 ≤ eval arg2 < m +// +// Postconditions: +// +// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m +// 0 ≤ eval out1 < m +func fiatScalarSub(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement, arg2 *fiatScalarMontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(arg1[0], arg2[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(arg1[1], arg2[1], uint64(fiatScalarUint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(arg1[2], arg2[2], uint64(fiatScalarUint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(arg1[3], arg2[3], uint64(fiatScalarUint1(x6))) + var x9 uint64 + fiatScalarCmovznzU64(&x9, fiatScalarUint1(x8), uint64(0x0), 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x1, (x9 & 0x5812631a5cf5d3ed), uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x3, (x9 & 0x14def9dea2f79cd6), uint64(fiatScalarUint1(x11))) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x5, uint64(0x0), uint64(fiatScalarUint1(x13))) + var x16 uint64 + x16, _ = bits.Add64(x7, (x9 & 0x1000000000000000), uint64(fiatScalarUint1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +// fiatScalarOpp negates a field element in the Montgomery domain. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// +// Postconditions: +// +// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m +// 0 ≤ eval out1 < m +func fiatScalarOpp(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement) { + var x1 uint64 + var x2 uint64 + x1, x2 = bits.Sub64(uint64(0x0), arg1[0], uint64(0x0)) + var x3 uint64 + var x4 uint64 + x3, x4 = bits.Sub64(uint64(0x0), arg1[1], uint64(fiatScalarUint1(x2))) + var x5 uint64 + var x6 uint64 + x5, x6 = bits.Sub64(uint64(0x0), arg1[2], uint64(fiatScalarUint1(x4))) + var x7 uint64 + var x8 uint64 + x7, x8 = bits.Sub64(uint64(0x0), arg1[3], uint64(fiatScalarUint1(x6))) + var x9 uint64 + fiatScalarCmovznzU64(&x9, fiatScalarUint1(x8), uint64(0x0), 0xffffffffffffffff) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x1, (x9 & 0x5812631a5cf5d3ed), uint64(0x0)) + var x12 uint64 + var x13 uint64 + x12, x13 = bits.Add64(x3, (x9 & 0x14def9dea2f79cd6), uint64(fiatScalarUint1(x11))) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(x5, uint64(0x0), uint64(fiatScalarUint1(x13))) + var x16 uint64 + x16, _ = bits.Add64(x7, (x9 & 0x1000000000000000), uint64(fiatScalarUint1(x15))) + out1[0] = x10 + out1[1] = x12 + out1[2] = x14 + out1[3] = x16 +} + +// fiatScalarNonzero outputs a single non-zero word if the input is non-zero and zero otherwise. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// +// Postconditions: +// +// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0 +// +// Input Bounds: +// +// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] +// +// Output Bounds: +// +// out1: [0x0 ~> 0xffffffffffffffff] +func fiatScalarNonzero(out1 *uint64, arg1 *[4]uint64) { + x1 := (arg1[0] | (arg1[1] | (arg1[2] | arg1[3]))) + *out1 = x1 +} + +// fiatScalarFromMontgomery translates a field element out of the Montgomery domain. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// +// Postconditions: +// +// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m +// 0 ≤ eval out1 < m +func fiatScalarFromMontgomery(out1 *fiatScalarNonMontgomeryDomainFieldElement, arg1 *fiatScalarMontgomeryDomainFieldElement) { + x1 := arg1[0] + var x2 uint64 + _, x2 = bits.Mul64(x1, 0xd2b51da312547e1b) + var x4 uint64 + var x5 uint64 + x5, x4 = bits.Mul64(x2, 0x1000000000000000) + var x6 uint64 + var x7 uint64 + x7, x6 = bits.Mul64(x2, 0x14def9dea2f79cd6) + var x8 uint64 + var x9 uint64 + x9, x8 = bits.Mul64(x2, 0x5812631a5cf5d3ed) + var x10 uint64 + var x11 uint64 + x10, x11 = bits.Add64(x9, x6, uint64(0x0)) + var x13 uint64 + _, x13 = bits.Add64(x1, x8, uint64(0x0)) + var x14 uint64 + var x15 uint64 + x14, x15 = bits.Add64(uint64(0x0), x10, uint64(fiatScalarUint1(x13))) + var x16 uint64 + var x17 uint64 + x16, x17 = bits.Add64(x14, arg1[1], uint64(0x0)) + var x18 uint64 + _, x18 = bits.Mul64(x16, 0xd2b51da312547e1b) + var x20 uint64 + var x21 uint64 + x21, x20 = bits.Mul64(x18, 0x1000000000000000) + var x22 uint64 + var x23 uint64 + x23, x22 = bits.Mul64(x18, 0x14def9dea2f79cd6) + var x24 uint64 + var x25 uint64 + x25, x24 = bits.Mul64(x18, 0x5812631a5cf5d3ed) + var x26 uint64 + var x27 uint64 + x26, x27 = bits.Add64(x25, x22, uint64(0x0)) + var x29 uint64 + _, x29 = bits.Add64(x16, x24, uint64(0x0)) + var x30 uint64 + var x31 uint64 + x30, x31 = bits.Add64((uint64(fiatScalarUint1(x17)) + (uint64(fiatScalarUint1(x15)) + (uint64(fiatScalarUint1(x11)) + x7))), x26, uint64(fiatScalarUint1(x29))) + var x32 uint64 + var x33 uint64 + x32, x33 = bits.Add64(x4, (uint64(fiatScalarUint1(x27)) + x23), uint64(fiatScalarUint1(x31))) + var x34 uint64 + var x35 uint64 + x34, x35 = bits.Add64(x5, x20, uint64(fiatScalarUint1(x33))) + var x36 uint64 + var x37 uint64 + x36, x37 = bits.Add64(x30, arg1[2], uint64(0x0)) + var x38 uint64 + var x39 uint64 + x38, x39 = bits.Add64(x32, uint64(0x0), uint64(fiatScalarUint1(x37))) + var x40 uint64 + var x41 uint64 + x40, x41 = bits.Add64(x34, uint64(0x0), uint64(fiatScalarUint1(x39))) + var x42 uint64 + _, x42 = bits.Mul64(x36, 0xd2b51da312547e1b) + var x44 uint64 + var x45 uint64 + x45, x44 = bits.Mul64(x42, 0x1000000000000000) + var x46 uint64 + var x47 uint64 + x47, x46 = bits.Mul64(x42, 0x14def9dea2f79cd6) + var x48 uint64 + var x49 uint64 + x49, x48 = bits.Mul64(x42, 0x5812631a5cf5d3ed) + var x50 uint64 + var x51 uint64 + x50, x51 = bits.Add64(x49, x46, uint64(0x0)) + var x53 uint64 + _, x53 = bits.Add64(x36, x48, uint64(0x0)) + var x54 uint64 + var x55 uint64 + x54, x55 = bits.Add64(x38, x50, uint64(fiatScalarUint1(x53))) + var x56 uint64 + var x57 uint64 + x56, x57 = bits.Add64(x40, (uint64(fiatScalarUint1(x51)) + x47), uint64(fiatScalarUint1(x55))) + var x58 uint64 + var x59 uint64 + x58, x59 = bits.Add64((uint64(fiatScalarUint1(x41)) + (uint64(fiatScalarUint1(x35)) + x21)), x44, uint64(fiatScalarUint1(x57))) + var x60 uint64 + var x61 uint64 + x60, x61 = bits.Add64(x54, arg1[3], uint64(0x0)) + var x62 uint64 + var x63 uint64 + x62, x63 = bits.Add64(x56, uint64(0x0), uint64(fiatScalarUint1(x61))) + var x64 uint64 + var x65 uint64 + x64, x65 = bits.Add64(x58, uint64(0x0), uint64(fiatScalarUint1(x63))) + var x66 uint64 + _, x66 = bits.Mul64(x60, 0xd2b51da312547e1b) + var x68 uint64 + var x69 uint64 + x69, x68 = bits.Mul64(x66, 0x1000000000000000) + var x70 uint64 + var x71 uint64 + x71, x70 = bits.Mul64(x66, 0x14def9dea2f79cd6) + var x72 uint64 + var x73 uint64 + x73, x72 = bits.Mul64(x66, 0x5812631a5cf5d3ed) + var x74 uint64 + var x75 uint64 + x74, x75 = bits.Add64(x73, x70, uint64(0x0)) + var x77 uint64 + _, x77 = bits.Add64(x60, x72, uint64(0x0)) + var x78 uint64 + var x79 uint64 + x78, x79 = bits.Add64(x62, x74, uint64(fiatScalarUint1(x77))) + var x80 uint64 + var x81 uint64 + x80, x81 = bits.Add64(x64, (uint64(fiatScalarUint1(x75)) + x71), uint64(fiatScalarUint1(x79))) + var x82 uint64 + var x83 uint64 + x82, x83 = bits.Add64((uint64(fiatScalarUint1(x65)) + (uint64(fiatScalarUint1(x59)) + x45)), x68, uint64(fiatScalarUint1(x81))) + x84 := (uint64(fiatScalarUint1(x83)) + x69) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Sub64(x78, 0x5812631a5cf5d3ed, uint64(0x0)) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Sub64(x80, 0x14def9dea2f79cd6, uint64(fiatScalarUint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Sub64(x82, uint64(0x0), uint64(fiatScalarUint1(x88))) + var x91 uint64 + var x92 uint64 + x91, x92 = bits.Sub64(x84, 0x1000000000000000, uint64(fiatScalarUint1(x90))) + var x94 uint64 + _, x94 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(fiatScalarUint1(x92))) + var x95 uint64 + fiatScalarCmovznzU64(&x95, fiatScalarUint1(x94), x85, x78) + var x96 uint64 + fiatScalarCmovznzU64(&x96, fiatScalarUint1(x94), x87, x80) + var x97 uint64 + fiatScalarCmovznzU64(&x97, fiatScalarUint1(x94), x89, x82) + var x98 uint64 + fiatScalarCmovznzU64(&x98, fiatScalarUint1(x94), x91, x84) + out1[0] = x95 + out1[1] = x96 + out1[2] = x97 + out1[3] = x98 +} + +// fiatScalarToMontgomery translates a field element into the Montgomery domain. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// +// Postconditions: +// +// eval (from_montgomery out1) mod m = eval arg1 mod m +// 0 ≤ eval out1 < m +func fiatScalarToMontgomery(out1 *fiatScalarMontgomeryDomainFieldElement, arg1 *fiatScalarNonMontgomeryDomainFieldElement) { + x1 := arg1[1] + x2 := arg1[2] + x3 := arg1[3] + x4 := arg1[0] + var x5 uint64 + var x6 uint64 + x6, x5 = bits.Mul64(x4, 0x399411b7c309a3d) + var x7 uint64 + var x8 uint64 + x8, x7 = bits.Mul64(x4, 0xceec73d217f5be65) + var x9 uint64 + var x10 uint64 + x10, x9 = bits.Mul64(x4, 0xd00e1ba768859347) + var x11 uint64 + var x12 uint64 + x12, x11 = bits.Mul64(x4, 0xa40611e3449c0f01) + var x13 uint64 + var x14 uint64 + x13, x14 = bits.Add64(x12, x9, uint64(0x0)) + var x15 uint64 + var x16 uint64 + x15, x16 = bits.Add64(x10, x7, uint64(fiatScalarUint1(x14))) + var x17 uint64 + var x18 uint64 + x17, x18 = bits.Add64(x8, x5, uint64(fiatScalarUint1(x16))) + var x19 uint64 + _, x19 = bits.Mul64(x11, 0xd2b51da312547e1b) + var x21 uint64 + var x22 uint64 + x22, x21 = bits.Mul64(x19, 0x1000000000000000) + var x23 uint64 + var x24 uint64 + x24, x23 = bits.Mul64(x19, 0x14def9dea2f79cd6) + var x25 uint64 + var x26 uint64 + x26, x25 = bits.Mul64(x19, 0x5812631a5cf5d3ed) + var x27 uint64 + var x28 uint64 + x27, x28 = bits.Add64(x26, x23, uint64(0x0)) + var x30 uint64 + _, x30 = bits.Add64(x11, x25, uint64(0x0)) + var x31 uint64 + var x32 uint64 + x31, x32 = bits.Add64(x13, x27, uint64(fiatScalarUint1(x30))) + var x33 uint64 + var x34 uint64 + x33, x34 = bits.Add64(x15, (uint64(fiatScalarUint1(x28)) + x24), uint64(fiatScalarUint1(x32))) + var x35 uint64 + var x36 uint64 + x35, x36 = bits.Add64(x17, x21, uint64(fiatScalarUint1(x34))) + var x37 uint64 + var x38 uint64 + x38, x37 = bits.Mul64(x1, 0x399411b7c309a3d) + var x39 uint64 + var x40 uint64 + x40, x39 = bits.Mul64(x1, 0xceec73d217f5be65) + var x41 uint64 + var x42 uint64 + x42, x41 = bits.Mul64(x1, 0xd00e1ba768859347) + var x43 uint64 + var x44 uint64 + x44, x43 = bits.Mul64(x1, 0xa40611e3449c0f01) + var x45 uint64 + var x46 uint64 + x45, x46 = bits.Add64(x44, x41, uint64(0x0)) + var x47 uint64 + var x48 uint64 + x47, x48 = bits.Add64(x42, x39, uint64(fiatScalarUint1(x46))) + var x49 uint64 + var x50 uint64 + x49, x50 = bits.Add64(x40, x37, uint64(fiatScalarUint1(x48))) + var x51 uint64 + var x52 uint64 + x51, x52 = bits.Add64(x31, x43, uint64(0x0)) + var x53 uint64 + var x54 uint64 + x53, x54 = bits.Add64(x33, x45, uint64(fiatScalarUint1(x52))) + var x55 uint64 + var x56 uint64 + x55, x56 = bits.Add64(x35, x47, uint64(fiatScalarUint1(x54))) + var x57 uint64 + var x58 uint64 + x57, x58 = bits.Add64(((uint64(fiatScalarUint1(x36)) + (uint64(fiatScalarUint1(x18)) + x6)) + x22), x49, uint64(fiatScalarUint1(x56))) + var x59 uint64 + _, x59 = bits.Mul64(x51, 0xd2b51da312547e1b) + var x61 uint64 + var x62 uint64 + x62, x61 = bits.Mul64(x59, 0x1000000000000000) + var x63 uint64 + var x64 uint64 + x64, x63 = bits.Mul64(x59, 0x14def9dea2f79cd6) + var x65 uint64 + var x66 uint64 + x66, x65 = bits.Mul64(x59, 0x5812631a5cf5d3ed) + var x67 uint64 + var x68 uint64 + x67, x68 = bits.Add64(x66, x63, uint64(0x0)) + var x70 uint64 + _, x70 = bits.Add64(x51, x65, uint64(0x0)) + var x71 uint64 + var x72 uint64 + x71, x72 = bits.Add64(x53, x67, uint64(fiatScalarUint1(x70))) + var x73 uint64 + var x74 uint64 + x73, x74 = bits.Add64(x55, (uint64(fiatScalarUint1(x68)) + x64), uint64(fiatScalarUint1(x72))) + var x75 uint64 + var x76 uint64 + x75, x76 = bits.Add64(x57, x61, uint64(fiatScalarUint1(x74))) + var x77 uint64 + var x78 uint64 + x78, x77 = bits.Mul64(x2, 0x399411b7c309a3d) + var x79 uint64 + var x80 uint64 + x80, x79 = bits.Mul64(x2, 0xceec73d217f5be65) + var x81 uint64 + var x82 uint64 + x82, x81 = bits.Mul64(x2, 0xd00e1ba768859347) + var x83 uint64 + var x84 uint64 + x84, x83 = bits.Mul64(x2, 0xa40611e3449c0f01) + var x85 uint64 + var x86 uint64 + x85, x86 = bits.Add64(x84, x81, uint64(0x0)) + var x87 uint64 + var x88 uint64 + x87, x88 = bits.Add64(x82, x79, uint64(fiatScalarUint1(x86))) + var x89 uint64 + var x90 uint64 + x89, x90 = bits.Add64(x80, x77, uint64(fiatScalarUint1(x88))) + var x91 uint64 + var x92 uint64 + x91, x92 = bits.Add64(x71, x83, uint64(0x0)) + var x93 uint64 + var x94 uint64 + x93, x94 = bits.Add64(x73, x85, uint64(fiatScalarUint1(x92))) + var x95 uint64 + var x96 uint64 + x95, x96 = bits.Add64(x75, x87, uint64(fiatScalarUint1(x94))) + var x97 uint64 + var x98 uint64 + x97, x98 = bits.Add64(((uint64(fiatScalarUint1(x76)) + (uint64(fiatScalarUint1(x58)) + (uint64(fiatScalarUint1(x50)) + x38))) + x62), x89, uint64(fiatScalarUint1(x96))) + var x99 uint64 + _, x99 = bits.Mul64(x91, 0xd2b51da312547e1b) + var x101 uint64 + var x102 uint64 + x102, x101 = bits.Mul64(x99, 0x1000000000000000) + var x103 uint64 + var x104 uint64 + x104, x103 = bits.Mul64(x99, 0x14def9dea2f79cd6) + var x105 uint64 + var x106 uint64 + x106, x105 = bits.Mul64(x99, 0x5812631a5cf5d3ed) + var x107 uint64 + var x108 uint64 + x107, x108 = bits.Add64(x106, x103, uint64(0x0)) + var x110 uint64 + _, x110 = bits.Add64(x91, x105, uint64(0x0)) + var x111 uint64 + var x112 uint64 + x111, x112 = bits.Add64(x93, x107, uint64(fiatScalarUint1(x110))) + var x113 uint64 + var x114 uint64 + x113, x114 = bits.Add64(x95, (uint64(fiatScalarUint1(x108)) + x104), uint64(fiatScalarUint1(x112))) + var x115 uint64 + var x116 uint64 + x115, x116 = bits.Add64(x97, x101, uint64(fiatScalarUint1(x114))) + var x117 uint64 + var x118 uint64 + x118, x117 = bits.Mul64(x3, 0x399411b7c309a3d) + var x119 uint64 + var x120 uint64 + x120, x119 = bits.Mul64(x3, 0xceec73d217f5be65) + var x121 uint64 + var x122 uint64 + x122, x121 = bits.Mul64(x3, 0xd00e1ba768859347) + var x123 uint64 + var x124 uint64 + x124, x123 = bits.Mul64(x3, 0xa40611e3449c0f01) + var x125 uint64 + var x126 uint64 + x125, x126 = bits.Add64(x124, x121, uint64(0x0)) + var x127 uint64 + var x128 uint64 + x127, x128 = bits.Add64(x122, x119, uint64(fiatScalarUint1(x126))) + var x129 uint64 + var x130 uint64 + x129, x130 = bits.Add64(x120, x117, uint64(fiatScalarUint1(x128))) + var x131 uint64 + var x132 uint64 + x131, x132 = bits.Add64(x111, x123, uint64(0x0)) + var x133 uint64 + var x134 uint64 + x133, x134 = bits.Add64(x113, x125, uint64(fiatScalarUint1(x132))) + var x135 uint64 + var x136 uint64 + x135, x136 = bits.Add64(x115, x127, uint64(fiatScalarUint1(x134))) + var x137 uint64 + var x138 uint64 + x137, x138 = bits.Add64(((uint64(fiatScalarUint1(x116)) + (uint64(fiatScalarUint1(x98)) + (uint64(fiatScalarUint1(x90)) + x78))) + x102), x129, uint64(fiatScalarUint1(x136))) + var x139 uint64 + _, x139 = bits.Mul64(x131, 0xd2b51da312547e1b) + var x141 uint64 + var x142 uint64 + x142, x141 = bits.Mul64(x139, 0x1000000000000000) + var x143 uint64 + var x144 uint64 + x144, x143 = bits.Mul64(x139, 0x14def9dea2f79cd6) + var x145 uint64 + var x146 uint64 + x146, x145 = bits.Mul64(x139, 0x5812631a5cf5d3ed) + var x147 uint64 + var x148 uint64 + x147, x148 = bits.Add64(x146, x143, uint64(0x0)) + var x150 uint64 + _, x150 = bits.Add64(x131, x145, uint64(0x0)) + var x151 uint64 + var x152 uint64 + x151, x152 = bits.Add64(x133, x147, uint64(fiatScalarUint1(x150))) + var x153 uint64 + var x154 uint64 + x153, x154 = bits.Add64(x135, (uint64(fiatScalarUint1(x148)) + x144), uint64(fiatScalarUint1(x152))) + var x155 uint64 + var x156 uint64 + x155, x156 = bits.Add64(x137, x141, uint64(fiatScalarUint1(x154))) + x157 := ((uint64(fiatScalarUint1(x156)) + (uint64(fiatScalarUint1(x138)) + (uint64(fiatScalarUint1(x130)) + x118))) + x142) + var x158 uint64 + var x159 uint64 + x158, x159 = bits.Sub64(x151, 0x5812631a5cf5d3ed, uint64(0x0)) + var x160 uint64 + var x161 uint64 + x160, x161 = bits.Sub64(x153, 0x14def9dea2f79cd6, uint64(fiatScalarUint1(x159))) + var x162 uint64 + var x163 uint64 + x162, x163 = bits.Sub64(x155, uint64(0x0), uint64(fiatScalarUint1(x161))) + var x164 uint64 + var x165 uint64 + x164, x165 = bits.Sub64(x157, 0x1000000000000000, uint64(fiatScalarUint1(x163))) + var x167 uint64 + _, x167 = bits.Sub64(uint64(0x0), uint64(0x0), uint64(fiatScalarUint1(x165))) + var x168 uint64 + fiatScalarCmovznzU64(&x168, fiatScalarUint1(x167), x158, x151) + var x169 uint64 + fiatScalarCmovznzU64(&x169, fiatScalarUint1(x167), x160, x153) + var x170 uint64 + fiatScalarCmovznzU64(&x170, fiatScalarUint1(x167), x162, x155) + var x171 uint64 + fiatScalarCmovznzU64(&x171, fiatScalarUint1(x167), x164, x157) + out1[0] = x168 + out1[1] = x169 + out1[2] = x170 + out1[3] = x171 +} + +// fiatScalarToBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. +// +// Preconditions: +// +// 0 ≤ eval arg1 < m +// +// Postconditions: +// +// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31] +// +// Input Bounds: +// +// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1fffffffffffffff]] +// +// Output Bounds: +// +// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1f]] +func fiatScalarToBytes(out1 *[32]uint8, arg1 *[4]uint64) { + x1 := arg1[3] + x2 := arg1[2] + x3 := arg1[1] + x4 := arg1[0] + x5 := (uint8(x4) & 0xff) + x6 := (x4 >> 8) + x7 := (uint8(x6) & 0xff) + x8 := (x6 >> 8) + x9 := (uint8(x8) & 0xff) + x10 := (x8 >> 8) + x11 := (uint8(x10) & 0xff) + x12 := (x10 >> 8) + x13 := (uint8(x12) & 0xff) + x14 := (x12 >> 8) + x15 := (uint8(x14) & 0xff) + x16 := (x14 >> 8) + x17 := (uint8(x16) & 0xff) + x18 := uint8((x16 >> 8)) + x19 := (uint8(x3) & 0xff) + x20 := (x3 >> 8) + x21 := (uint8(x20) & 0xff) + x22 := (x20 >> 8) + x23 := (uint8(x22) & 0xff) + x24 := (x22 >> 8) + x25 := (uint8(x24) & 0xff) + x26 := (x24 >> 8) + x27 := (uint8(x26) & 0xff) + x28 := (x26 >> 8) + x29 := (uint8(x28) & 0xff) + x30 := (x28 >> 8) + x31 := (uint8(x30) & 0xff) + x32 := uint8((x30 >> 8)) + x33 := (uint8(x2) & 0xff) + x34 := (x2 >> 8) + x35 := (uint8(x34) & 0xff) + x36 := (x34 >> 8) + x37 := (uint8(x36) & 0xff) + x38 := (x36 >> 8) + x39 := (uint8(x38) & 0xff) + x40 := (x38 >> 8) + x41 := (uint8(x40) & 0xff) + x42 := (x40 >> 8) + x43 := (uint8(x42) & 0xff) + x44 := (x42 >> 8) + x45 := (uint8(x44) & 0xff) + x46 := uint8((x44 >> 8)) + x47 := (uint8(x1) & 0xff) + x48 := (x1 >> 8) + x49 := (uint8(x48) & 0xff) + x50 := (x48 >> 8) + x51 := (uint8(x50) & 0xff) + x52 := (x50 >> 8) + x53 := (uint8(x52) & 0xff) + x54 := (x52 >> 8) + x55 := (uint8(x54) & 0xff) + x56 := (x54 >> 8) + x57 := (uint8(x56) & 0xff) + x58 := (x56 >> 8) + x59 := (uint8(x58) & 0xff) + x60 := uint8((x58 >> 8)) + out1[0] = x5 + out1[1] = x7 + out1[2] = x9 + out1[3] = x11 + out1[4] = x13 + out1[5] = x15 + out1[6] = x17 + out1[7] = x18 + out1[8] = x19 + out1[9] = x21 + out1[10] = x23 + out1[11] = x25 + out1[12] = x27 + out1[13] = x29 + out1[14] = x31 + out1[15] = x32 + out1[16] = x33 + out1[17] = x35 + out1[18] = x37 + out1[19] = x39 + out1[20] = x41 + out1[21] = x43 + out1[22] = x45 + out1[23] = x46 + out1[24] = x47 + out1[25] = x49 + out1[26] = x51 + out1[27] = x53 + out1[28] = x55 + out1[29] = x57 + out1[30] = x59 + out1[31] = x60 +} + +// fiatScalarFromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. +// +// Preconditions: +// +// 0 ≤ bytes_eval arg1 < m +// +// Postconditions: +// +// eval out1 mod m = bytes_eval arg1 mod m +// 0 ≤ eval out1 < m +// +// Input Bounds: +// +// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0x1f]] +// +// Output Bounds: +// +// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0x1fffffffffffffff]] +func fiatScalarFromBytes(out1 *[4]uint64, arg1 *[32]uint8) { + x1 := (uint64(arg1[31]) << 56) + x2 := (uint64(arg1[30]) << 48) + x3 := (uint64(arg1[29]) << 40) + x4 := (uint64(arg1[28]) << 32) + x5 := (uint64(arg1[27]) << 24) + x6 := (uint64(arg1[26]) << 16) + x7 := (uint64(arg1[25]) << 8) + x8 := arg1[24] + x9 := (uint64(arg1[23]) << 56) + x10 := (uint64(arg1[22]) << 48) + x11 := (uint64(arg1[21]) << 40) + x12 := (uint64(arg1[20]) << 32) + x13 := (uint64(arg1[19]) << 24) + x14 := (uint64(arg1[18]) << 16) + x15 := (uint64(arg1[17]) << 8) + x16 := arg1[16] + x17 := (uint64(arg1[15]) << 56) + x18 := (uint64(arg1[14]) << 48) + x19 := (uint64(arg1[13]) << 40) + x20 := (uint64(arg1[12]) << 32) + x21 := (uint64(arg1[11]) << 24) + x22 := (uint64(arg1[10]) << 16) + x23 := (uint64(arg1[9]) << 8) + x24 := arg1[8] + x25 := (uint64(arg1[7]) << 56) + x26 := (uint64(arg1[6]) << 48) + x27 := (uint64(arg1[5]) << 40) + x28 := (uint64(arg1[4]) << 32) + x29 := (uint64(arg1[3]) << 24) + x30 := (uint64(arg1[2]) << 16) + x31 := (uint64(arg1[1]) << 8) + x32 := arg1[0] + x33 := (x31 + uint64(x32)) + x34 := (x30 + x33) + x35 := (x29 + x34) + x36 := (x28 + x35) + x37 := (x27 + x36) + x38 := (x26 + x37) + x39 := (x25 + x38) + x40 := (x23 + uint64(x24)) + x41 := (x22 + x40) + x42 := (x21 + x41) + x43 := (x20 + x42) + x44 := (x19 + x43) + x45 := (x18 + x44) + x46 := (x17 + x45) + x47 := (x15 + uint64(x16)) + x48 := (x14 + x47) + x49 := (x13 + x48) + x50 := (x12 + x49) + x51 := (x11 + x50) + x52 := (x10 + x51) + x53 := (x9 + x52) + x54 := (x7 + uint64(x8)) + x55 := (x6 + x54) + x56 := (x5 + x55) + x57 := (x4 + x56) + x58 := (x3 + x57) + x59 := (x2 + x58) + x60 := (x1 + x59) + out1[0] = x39 + out1[1] = x46 + out1[2] = x53 + out1[3] = x60 +} diff --git a/vendor/filippo.io/edwards25519/scalarmult.go b/vendor/filippo.io/edwards25519/scalarmult.go new file mode 100644 index 00000000..f7ca3cef --- /dev/null +++ b/vendor/filippo.io/edwards25519/scalarmult.go @@ -0,0 +1,214 @@ +// Copyright (c) 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 edwards25519 + +import "sync" + +// basepointTable is a set of 32 affineLookupTables, where table i is generated +// from 256i * basepoint. It is precomputed the first time it's used. +func basepointTable() *[32]affineLookupTable { + basepointTablePrecomp.initOnce.Do(func() { + p := NewGeneratorPoint() + for i := 0; i < 32; i++ { + basepointTablePrecomp.table[i].FromP3(p) + for j := 0; j < 8; j++ { + p.Add(p, p) + } + } + }) + return &basepointTablePrecomp.table +} + +var basepointTablePrecomp struct { + table [32]affineLookupTable + initOnce sync.Once +} + +// ScalarBaseMult sets v = x * B, where B is the canonical generator, and +// returns v. +// +// The scalar multiplication is done in constant time. +func (v *Point) ScalarBaseMult(x *Scalar) *Point { + basepointTable := basepointTable() + + // Write x = sum(x_i * 16^i) so x*B = sum( B*x_i*16^i ) + // as described in the Ed25519 paper + // + // Group even and odd coefficients + // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B + // + x_1*16^1*B + x_3*16^3*B + ... + x_63*16^63*B + // x*B = x_0*16^0*B + x_2*16^2*B + ... + x_62*16^62*B + // + 16*( x_1*16^0*B + x_3*16^2*B + ... + x_63*16^62*B) + // + // We use a lookup table for each i to get x_i*16^(2*i)*B + // and do four doublings to multiply by 16. + digits := x.signedRadix16() + + multiple := &affineCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + + // Accumulate the odd components first + v.Set(NewIdentityPoint()) + for i := 1; i < 64; i += 2 { + basepointTable[i/2].SelectInto(multiple, digits[i]) + tmp1.AddAffine(v, multiple) + v.fromP1xP1(tmp1) + } + + // Multiply by 16 + tmp2.FromP3(v) // tmp2 = v in P2 coords + tmp1.Double(tmp2) // tmp1 = 2*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 2*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 4*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 4*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 8*v in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 8*v in P2 coords + tmp1.Double(tmp2) // tmp1 = 16*v in P1xP1 coords + v.fromP1xP1(tmp1) // now v = 16*(odd components) + + // Accumulate the even components + for i := 0; i < 64; i += 2 { + basepointTable[i/2].SelectInto(multiple, digits[i]) + tmp1.AddAffine(v, multiple) + v.fromP1xP1(tmp1) + } + + return v +} + +// ScalarMult sets v = x * q, and returns v. +// +// The scalar multiplication is done in constant time. +func (v *Point) ScalarMult(x *Scalar, q *Point) *Point { + checkInitialized(q) + + var table projLookupTable + table.FromP3(q) + + // Write x = sum(x_i * 16^i) + // so x*Q = sum( Q*x_i*16^i ) + // = Q*x_0 + 16*(Q*x_1 + 16*( ... + Q*x_63) ... ) + // <------compute inside out--------- + // + // We use the lookup table to get the x_i*Q values + // and do four doublings to compute 16*Q + digits := x.signedRadix16() + + // Unwrap first loop iteration to save computing 16*identity + multiple := &projCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + table.SelectInto(multiple, digits[63]) + + v.Set(NewIdentityPoint()) + tmp1.Add(v, multiple) // tmp1 = x_63*Q in P1xP1 coords + for i := 62; i >= 0; i-- { + tmp2.FromP1xP1(tmp1) // tmp2 = (prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 2*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 2*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 4*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 4*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 8*(prev) in P1xP1 coords + tmp2.FromP1xP1(tmp1) // tmp2 = 8*(prev) in P2 coords + tmp1.Double(tmp2) // tmp1 = 16*(prev) in P1xP1 coords + v.fromP1xP1(tmp1) // v = 16*(prev) in P3 coords + table.SelectInto(multiple, digits[i]) + tmp1.Add(v, multiple) // tmp1 = x_i*Q + 16*(prev) in P1xP1 coords + } + v.fromP1xP1(tmp1) + return v +} + +// basepointNafTable is the nafLookupTable8 for the basepoint. +// It is precomputed the first time it's used. +func basepointNafTable() *nafLookupTable8 { + basepointNafTablePrecomp.initOnce.Do(func() { + basepointNafTablePrecomp.table.FromP3(NewGeneratorPoint()) + }) + return &basepointNafTablePrecomp.table +} + +var basepointNafTablePrecomp struct { + table nafLookupTable8 + initOnce sync.Once +} + +// VarTimeDoubleScalarBaseMult sets v = a * A + b * B, where B is the canonical +// generator, and returns v. +// +// Execution time depends on the inputs. +func (v *Point) VarTimeDoubleScalarBaseMult(a *Scalar, A *Point, b *Scalar) *Point { + checkInitialized(A) + + // Similarly to the single variable-base approach, we compute + // digits and use them with a lookup table. However, because + // we are allowed to do variable-time operations, we don't + // need constant-time lookups or constant-time digit + // computations. + // + // So we use a non-adjacent form of some width w instead of + // radix 16. This is like a binary representation (one digit + // for each binary place) but we allow the digits to grow in + // magnitude up to 2^{w-1} so that the nonzero digits are as + // sparse as possible. Intuitively, this "condenses" the + // "mass" of the scalar onto sparse coefficients (meaning + // fewer additions). + + basepointNafTable := basepointNafTable() + var aTable nafLookupTable5 + aTable.FromP3(A) + // Because the basepoint is fixed, we can use a wider NAF + // corresponding to a bigger table. + aNaf := a.nonAdjacentForm(5) + bNaf := b.nonAdjacentForm(8) + + // Find the first nonzero coefficient. + i := 255 + for j := i; j >= 0; j-- { + if aNaf[j] != 0 || bNaf[j] != 0 { + break + } + } + + multA := &projCached{} + multB := &affineCached{} + tmp1 := &projP1xP1{} + tmp2 := &projP2{} + tmp2.Zero() + + // Move from high to low bits, doubling the accumulator + // at each iteration and checking whether there is a nonzero + // coefficient to look up a multiple of. + for ; i >= 0; i-- { + tmp1.Double(tmp2) + + // Only update v if we have a nonzero coeff to add in. + if aNaf[i] > 0 { + v.fromP1xP1(tmp1) + aTable.SelectInto(multA, aNaf[i]) + tmp1.Add(v, multA) + } else if aNaf[i] < 0 { + v.fromP1xP1(tmp1) + aTable.SelectInto(multA, -aNaf[i]) + tmp1.Sub(v, multA) + } + + if bNaf[i] > 0 { + v.fromP1xP1(tmp1) + basepointNafTable.SelectInto(multB, bNaf[i]) + tmp1.AddAffine(v, multB) + } else if bNaf[i] < 0 { + v.fromP1xP1(tmp1) + basepointNafTable.SelectInto(multB, -bNaf[i]) + tmp1.SubAffine(v, multB) + } + + tmp2.FromP1xP1(tmp1) + } + + v.fromP2(tmp2) + return v +} diff --git a/vendor/filippo.io/edwards25519/tables.go b/vendor/filippo.io/edwards25519/tables.go new file mode 100644 index 00000000..83234bbc --- /dev/null +++ b/vendor/filippo.io/edwards25519/tables.go @@ -0,0 +1,129 @@ +// Copyright (c) 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 edwards25519 + +import ( + "crypto/subtle" +) + +// A dynamic lookup table for variable-base, constant-time scalar muls. +type projLookupTable struct { + points [8]projCached +} + +// A precomputed lookup table for fixed-base, constant-time scalar muls. +type affineLookupTable struct { + points [8]affineCached +} + +// A dynamic lookup table for variable-base, variable-time scalar muls. +type nafLookupTable5 struct { + points [8]projCached +} + +// A precomputed lookup table for fixed-base, variable-time scalar muls. +type nafLookupTable8 struct { + points [64]affineCached +} + +// Constructors. + +// Builds a lookup table at runtime. Fast. +func (v *projLookupTable) FromP3(q *Point) { + // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q + // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q + v.points[0].FromP3(q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + // Compute (i+1)*Q as Q + i*Q and convert to a projCached + // This is needlessly complicated because the API has explicit + // receivers instead of creating stack objects and relying on RVO + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(q, &v.points[i]))) + } +} + +// This is not optimised for speed; fixed-base tables should be precomputed. +func (v *affineLookupTable) FromP3(q *Point) { + // Goal: v.points[i] = (i+1)*Q, i.e., Q, 2Q, ..., 8Q + // This allows lookup of -8Q, ..., -Q, 0, Q, ..., 8Q + v.points[0].FromP3(q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + // Compute (i+1)*Q as Q + i*Q and convert to affineCached + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(q, &v.points[i]))) + } +} + +// Builds a lookup table at runtime. Fast. +func (v *nafLookupTable5) FromP3(q *Point) { + // Goal: v.points[i] = (2*i+1)*Q, i.e., Q, 3Q, 5Q, ..., 15Q + // This allows lookup of -15Q, ..., -3Q, -Q, 0, Q, 3Q, ..., 15Q + v.points[0].FromP3(q) + q2 := Point{} + q2.Add(q, q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 7; i++ { + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.Add(&q2, &v.points[i]))) + } +} + +// This is not optimised for speed; fixed-base tables should be precomputed. +func (v *nafLookupTable8) FromP3(q *Point) { + v.points[0].FromP3(q) + q2 := Point{} + q2.Add(q, q) + tmpP3 := Point{} + tmpP1xP1 := projP1xP1{} + for i := 0; i < 63; i++ { + v.points[i+1].FromP3(tmpP3.fromP1xP1(tmpP1xP1.AddAffine(&q2, &v.points[i]))) + } +} + +// Selectors. + +// Set dest to x*Q, where -8 <= x <= 8, in constant time. +func (v *projLookupTable) SelectInto(dest *projCached, x int8) { + // Compute xabs = |x| + xmask := x >> 7 + xabs := uint8((x + xmask) ^ xmask) + + dest.Zero() + for j := 1; j <= 8; j++ { + // Set dest = j*Q if |x| = j + cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) + dest.Select(&v.points[j-1], dest, cond) + } + // Now dest = |x|*Q, conditionally negate to get x*Q + dest.CondNeg(int(xmask & 1)) +} + +// Set dest to x*Q, where -8 <= x <= 8, in constant time. +func (v *affineLookupTable) SelectInto(dest *affineCached, x int8) { + // Compute xabs = |x| + xmask := x >> 7 + xabs := uint8((x + xmask) ^ xmask) + + dest.Zero() + for j := 1; j <= 8; j++ { + // Set dest = j*Q if |x| = j + cond := subtle.ConstantTimeByteEq(xabs, uint8(j)) + dest.Select(&v.points[j-1], dest, cond) + } + // Now dest = |x|*Q, conditionally negate to get x*Q + dest.CondNeg(int(xmask & 1)) +} + +// Given odd x with 0 < x < 2^4, return x*Q (in variable time). +func (v *nafLookupTable5) SelectInto(dest *projCached, x int8) { + *dest = v.points[x/2] +} + +// Given odd x with 0 < x < 2^7, return x*Q (in variable time). +func (v *nafLookupTable8) SelectInto(dest *affineCached, x int8) { + *dest = v.points[x/2] +} diff --git a/vendor/github.com/alexbrainman/sspi/LICENSE b/vendor/github.com/alexbrainman/sspi/LICENSE new file mode 100644 index 00000000..74487567 --- /dev/null +++ b/vendor/github.com/alexbrainman/sspi/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/alexbrainman/sspi/README.md b/vendor/github.com/alexbrainman/sspi/README.md new file mode 100644 index 00000000..848b6b58 --- /dev/null +++ b/vendor/github.com/alexbrainman/sspi/README.md @@ -0,0 +1 @@ +This repository holds Go packages for accessing Security Support Provider Interface on Windows. diff --git a/vendor/github.com/alexbrainman/sspi/buffer.go b/vendor/github.com/alexbrainman/sspi/buffer.go new file mode 100644 index 00000000..c812e8eb --- /dev/null +++ b/vendor/github.com/alexbrainman/sspi/buffer.go @@ -0,0 +1,57 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package sspi + +import ( + "io" + "unsafe" +) + +func (b *SecBuffer) Set(buftype uint32, data []byte) { + b.BufferType = buftype + if len(data) > 0 { + b.Buffer = &data[0] + b.BufferSize = uint32(len(data)) + } else { + b.Buffer = nil + b.BufferSize = 0 + } +} + +func (b *SecBuffer) Free() error { + if b.Buffer == nil { + return nil + } + return FreeContextBuffer((*byte)(unsafe.Pointer(b.Buffer))) +} + +func (b *SecBuffer) Bytes() []byte { + if b.Buffer == nil || b.BufferSize <= 0 { + return nil + } + return (*[(1 << 31) - 1]byte)(unsafe.Pointer(b.Buffer))[:b.BufferSize] +} + +func (b *SecBuffer) WriteAll(w io.Writer) (int, error) { + if b.BufferSize == 0 || b.Buffer == nil { + return 0, nil + } + data := b.Bytes() + total := 0 + for { + n, err := w.Write(data) + total += n + if err != nil { + return total, err + } + if n >= len(data) { + break + } + data = data[n:] + } + return total, nil +} diff --git a/vendor/github.com/alexbrainman/sspi/internal/common/common.go b/vendor/github.com/alexbrainman/sspi/internal/common/common.go new file mode 100644 index 00000000..7ccf4d50 --- /dev/null +++ b/vendor/github.com/alexbrainman/sspi/internal/common/common.go @@ -0,0 +1,152 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package common + +import ( + "errors" + "syscall" + + "github.com/alexbrainman/sspi" +) + +func BuildAuthIdentity(domain, username, password string) (*sspi.SEC_WINNT_AUTH_IDENTITY, error) { + if len(username) == 0 { + return nil, errors.New("username parameter cannot be empty") + } + d, err := syscall.UTF16FromString(domain) + if err != nil { + return nil, err + } + u, err := syscall.UTF16FromString(username) + if err != nil { + return nil, err + } + p, err := syscall.UTF16FromString(password) + if err != nil { + return nil, err + } + return &sspi.SEC_WINNT_AUTH_IDENTITY{ + User: &u[0], + UserLength: uint32(len(u) - 1), // do not count terminating 0 + Domain: &d[0], + DomainLength: uint32(len(d) - 1), // do not count terminating 0 + Password: &p[0], + PasswordLength: uint32(len(p) - 1), // do not count terminating 0 + Flags: sspi.SEC_WINNT_AUTH_IDENTITY_UNICODE, + }, nil +} + +func UpdateContext(c *sspi.Context, dst, src []byte, targetName *uint16) (authCompleted bool, n int, err error) { + var inBuf, outBuf [1]sspi.SecBuffer + inBuf[0].Set(sspi.SECBUFFER_TOKEN, src) + inBufs := &sspi.SecBufferDesc{ + Version: sspi.SECBUFFER_VERSION, + BuffersCount: 1, + Buffers: &inBuf[0], + } + outBuf[0].Set(sspi.SECBUFFER_TOKEN, dst) + outBufs := &sspi.SecBufferDesc{ + Version: sspi.SECBUFFER_VERSION, + BuffersCount: 1, + Buffers: &outBuf[0], + } + ret := c.Update(targetName, outBufs, inBufs) + switch ret { + case sspi.SEC_E_OK: + // session established -> return success + return true, int(outBuf[0].BufferSize), nil + case sspi.SEC_I_COMPLETE_NEEDED, sspi.SEC_I_COMPLETE_AND_CONTINUE: + ret = sspi.CompleteAuthToken(c.Handle, outBufs) + if ret != sspi.SEC_E_OK { + return false, 0, ret + } + case sspi.SEC_I_CONTINUE_NEEDED: + default: + return false, 0, ret + } + return false, int(outBuf[0].BufferSize), nil +} + +func MakeSignature(c *sspi.Context, msg []byte, qop, seqno uint32) ([]byte, error) { + _, maxSignature, _, _, err := c.Sizes() + if err != nil { + return nil, err + } + + if maxSignature == 0 { + return nil, errors.New("integrity services are not requested or unavailable") + } + + var b [2]sspi.SecBuffer + b[0].Set(sspi.SECBUFFER_DATA, msg) + b[1].Set(sspi.SECBUFFER_TOKEN, make([]byte, maxSignature)) + + ret := sspi.MakeSignature(c.Handle, qop, sspi.NewSecBufferDesc(b[:]), seqno) + if ret != sspi.SEC_E_OK { + return nil, ret + } + + return b[1].Bytes(), nil +} + +func EncryptMessage(c *sspi.Context, msg []byte, qop, seqno uint32) ([]byte, error) { + _ /*maxToken*/, maxSignature, cBlockSize, cSecurityTrailer, err := c.Sizes() + if err != nil { + return nil, err + } + + if maxSignature == 0 { + return nil, errors.New("integrity services are not requested or unavailable") + } + + var b [3]sspi.SecBuffer + b[0].Set(sspi.SECBUFFER_TOKEN, make([]byte, cSecurityTrailer)) + b[1].Set(sspi.SECBUFFER_DATA, msg) + b[2].Set(sspi.SECBUFFER_PADDING, make([]byte, cBlockSize)) + + ret := sspi.EncryptMessage(c.Handle, qop, sspi.NewSecBufferDesc(b[:]), seqno) + if ret != sspi.SEC_E_OK { + return nil, ret + } + + r0, r1, r2 := b[0].Bytes(), b[1].Bytes(), b[2].Bytes() + res := make([]byte, 0, len(r0)+len(r1)+len(r2)) + res = append(res, r0...) + res = append(res, r1...) + res = append(res, r2...) + + return res, nil +} + +func DecryptMessage(c *sspi.Context, msg []byte, seqno uint32) (uint32, []byte, error) { + var b [2]sspi.SecBuffer + b[0].Set(sspi.SECBUFFER_STREAM, msg) + b[1].Set(sspi.SECBUFFER_DATA, []byte{}) + + var qop uint32 + ret := sspi.DecryptMessage(c.Handle, sspi.NewSecBufferDesc(b[:]), seqno, &qop) + if ret != sspi.SEC_E_OK { + return qop, nil, ret + } + + return qop, b[1].Bytes(), nil +} + +func VerifySignature(c *sspi.Context, msg, token []byte, seqno uint32) (uint32, error) { + var b [2]sspi.SecBuffer + b[0].Set(sspi.SECBUFFER_DATA, msg) + b[1].Set(sspi.SECBUFFER_TOKEN, token) + + var qop uint32 + + ret := sspi.VerifySignature(c.Handle, sspi.NewSecBufferDesc(b[:]), seqno, &qop) + if ret != sspi.SEC_E_OK { + return 0, ret + } + + return qop, nil +} diff --git a/vendor/github.com/alexbrainman/sspi/mksyscall.go b/vendor/github.com/alexbrainman/sspi/mksyscall.go new file mode 100644 index 00000000..19e11959 --- /dev/null +++ b/vendor/github.com/alexbrainman/sspi/mksyscall.go @@ -0,0 +1,7 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sspi + +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -systemdll=false -output=zsyscall_windows.go syscall.go diff --git a/vendor/github.com/alexbrainman/sspi/negotiate/negotiate.go b/vendor/github.com/alexbrainman/sspi/negotiate/negotiate.go new file mode 100644 index 00000000..b7ef256b --- /dev/null +++ b/vendor/github.com/alexbrainman/sspi/negotiate/negotiate.go @@ -0,0 +1,368 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows +// +build windows + +// Package negotiate provides access to the Microsoft Negotiate SSP Package. +package negotiate + +import ( + "errors" + "sync" + "syscall" + "time" + "unsafe" + + "github.com/alexbrainman/sspi" + "github.com/alexbrainman/sspi/internal/common" +) + +// TODO: maybe (if possible) move all winapi related out of sspi and into sspi/internal/winapi + +// PackageInfo contains the Negotiate SSP package description. +// +// It's initialized best-effort during init. During early boot it may not +// yet be loaded & available and thus this will be nil. +// +// Deprecated: use GetPackageInfo instead. +var PackageInfo *sspi.PackageInfo + +func init() { + PackageInfo, _ = GetPackageInfo() +} + +var ( + pkgInfoMu sync.Mutex + pkgInfo *sspi.PackageInfo +) + +// GetPackageInfo returns the Negotiate SSP package description. +func GetPackageInfo() (*sspi.PackageInfo, error) { + pkgInfoMu.Lock() + defer pkgInfoMu.Unlock() + if pkgInfo != nil { + return pkgInfo, nil + } + v, err := sspi.QueryPackageInfo(sspi.NEGOSSP_NAME) + if err != nil { + return nil, err + } + pkgInfo = v + return v, nil +} + +func acquireCredentials(principalName string, creduse uint32, ai *sspi.SEC_WINNT_AUTH_IDENTITY) (*sspi.Credentials, error) { + c, err := sspi.AcquireCredentials(principalName, sspi.NEGOSSP_NAME, creduse, (*byte)(unsafe.Pointer(ai))) + if err != nil { + return nil, err + } + return c, nil +} + +// AcquireCurrentUserCredentials acquires credentials of currently +// logged on user. These will be used by the client to authenticate +// itself to the server. It will also be used by the server +// to impersonate the user. +func AcquireCurrentUserCredentials() (*sspi.Credentials, error) { + return acquireCredentials("", sspi.SECPKG_CRED_OUTBOUND, nil) +} + +// AcquireUserCredentials acquires credentials of user described by +// domain, username and password. These will be used by the client to +// authenticate itself to the server. It will also be used by the +// server to impersonate the user. +func AcquireUserCredentials(domain, username, password string) (*sspi.Credentials, error) { + ai, err := common.BuildAuthIdentity(domain, username, password) + if err != nil { + return nil, err + } + return acquireCredentials("", sspi.SECPKG_CRED_OUTBOUND, ai) +} + +// AcquireServerCredentials acquires server credentials that will +// be used to authenticate clients. +// The principalName parameter is passed to the underlying call to +// the winapi AcquireCredentialsHandle function (and specifies the +// name of the principal whose credentials the underlying handle +// will reference). +// As a special case, using an empty string for the principal name +// will require the credential of the user under whose security context +// the current process is running. +func AcquireServerCredentials(principalName string) (*sspi.Credentials, error) { + return acquireCredentials(principalName, sspi.SECPKG_CRED_INBOUND, nil) +} + +// ClientContext is used by the client to manage all steps of Negotiate negotiation. +type ClientContext struct { + sctxt *sspi.Context + targetName *uint16 +} + +// NewClientContext creates a new client context. It uses client +// credentials cred generated by AcquireCurrentUserCredentials or +// AcquireUserCredentials and SPN to start a client Negotiate +// negotiation sequence. targetName is the service principal name +// (SPN) or the security context of the destination server. +// NewClientContext returns a new token to be sent to the server. +func NewClientContext(cred *sspi.Credentials, targetName string) (cc *ClientContext, outputToken []byte, err error) { + return NewClientContextWithFlags(cred, targetName, sspi.ISC_REQ_CONNECTION) +} + +// NewClientContextWithFlags creates a new client context. It uses client +// credentials cred generated by AcquireCurrentUserCredentials or +// AcquireUserCredentials and SPN to start a client Negotiate +// negotiation sequence. targetName is the service principal name +// (SPN) or the security context of the destination server. +// The flags parameter is used to indicate requests for the context +// (for example sspi.ISC_REQ_CONFIDENTIALITY|sspi.ISC_REQ_REPLAY_DETECT) +// NewClientContextWithFlags returns a new token to be sent to the server. +func NewClientContextWithFlags(cred *sspi.Credentials, targetName string, flags uint32) (cc *ClientContext, outputToken []byte, err error) { + var tname *uint16 + if len(targetName) > 0 { + p, err2 := syscall.UTF16FromString(targetName) + if err2 != nil { + return nil, nil, err2 + } + if len(p) > 0 { + tname = &p[0] + } + } + pkgInfo, err := GetPackageInfo() + if err != nil { + return nil, nil, err + } + otoken := make([]byte, pkgInfo.MaxToken) + c := sspi.NewClientContext(cred, flags) + + authCompleted, n, err2 := common.UpdateContext(c, otoken, nil, tname) + if err2 != nil { + return nil, nil, err2 + } + if authCompleted { + c.Release() + return nil, nil, errors.New("negotiate authentication should not be completed yet") + } + if n == 0 { + c.Release() + return nil, nil, errors.New("negotiate token should not be empty") + } + otoken = otoken[:n] + return &ClientContext{sctxt: c, targetName: tname}, otoken, nil +} + +// Release free up resources associated with client context c. +func (c *ClientContext) Release() error { + if c == nil { + return nil + } + return c.sctxt.Release() +} + +// Expiry returns c expiry time. +func (c *ClientContext) Expiry() time.Time { + return c.sctxt.Expiry() +} + +// Update advances client part of Negotiate negotiation c. It uses +// token received from the server and returns true if client part +// of authentication is complete. It also returns new token to be +// sent to the server. +func (c *ClientContext) Update(token []byte) (authCompleted bool, outputToken []byte, err error) { + pkgInfo, err := GetPackageInfo() + if err != nil { + return false, nil, err + } + otoken := make([]byte, pkgInfo.MaxToken) + authDone, n, err2 := common.UpdateContext(c.sctxt, otoken, token, c.targetName) + if err2 != nil { + return false, nil, err2 + } + if n == 0 && !authDone { + return false, nil, errors.New("negotiate token should not be empty") + } + otoken = otoken[:n] + return authDone, otoken, nil +} + +// Sizes queries the client context for the sizes used in per-message +// functions. It returns the maximum token size used in authentication +// exchanges, the maximum signature size, the preferred integral size of +// messages, the size of any security trailer, and any error. +func (c *ClientContext) Sizes() (uint32, uint32, uint32, uint32, error) { + return c.sctxt.Sizes() +} + +// MakeSignature uses the established client context to create a signature +// for the given message using the provided quality of protection flags and +// sequence number. It returns the signature token in addition to any error. +func (c *ClientContext) MakeSignature(msg []byte, qop, seqno uint32) ([]byte, error) { + return common.MakeSignature(c.sctxt, msg, qop, seqno) +} + +// VerifySignature uses the established client context and signature token +// to check that the provided message hasn't been tampered or received out +// of sequence. It returns any quality of protection flags and any error +// that occurred. +func (c *ClientContext) VerifySignature(msg, token []byte, seqno uint32) (uint32, error) { + return common.VerifySignature(c.sctxt, msg, token, seqno) +} + +// EncryptMessage uses the established client context to encrypt a message +// using the provided quality of protection flags and sequence number. +// It returns the signature token in addition to any error. +// IMPORTANT: the input msg parameter is updated in place by the low-level windows api +// so must be copied if the initial content should not be modified. +func (c *ClientContext) EncryptMessage(msg []byte, qop, seqno uint32) ([]byte, error) { + return common.EncryptMessage(c.sctxt, msg, qop, seqno) +} + +// DecryptMessage uses the established client context to decrypt a message +// using the provided sequence number. +// It returns the quality of protection flag and the decrypted message in addition to any error. +func (c *ClientContext) DecryptMessage(msg []byte, seqno uint32) (uint32, []byte, error) { + return common.DecryptMessage(c.sctxt, msg, seqno) +} + +// VerifyFlags determines if all flags used to construct the client context +// were honored (see NewClientContextWithFlags). It should be called after c.Update. +func (c *ClientContext) VerifyFlags() error { + return c.sctxt.VerifyFlags() +} + +// VerifySelectiveFlags determines if the given flags were honored (see NewClientContextWithFlags). +// It should be called after c.Update. +func (c *ClientContext) VerifySelectiveFlags(flags uint32) error { + return c.sctxt.VerifySelectiveFlags(flags) +} + +// ServerContext is used by the server to manage all steps of Negotiate +// negotiation. Once authentication is completed the context can be +// used to impersonate client. +type ServerContext struct { + sctxt *sspi.Context +} + +// NewServerContext creates new server context. It uses server +// credentials created by AcquireServerCredentials and token from +// the client to start server Negotiate negotiation sequence. +// It also returns new token to be sent to the client. +func NewServerContext(cred *sspi.Credentials, token []byte) (sc *ServerContext, authDone bool, outputToken []byte, err error) { + pkgInfo, err := GetPackageInfo() + if err != nil { + return nil, false, nil, err + } + otoken := make([]byte, pkgInfo.MaxToken) + c := sspi.NewServerContext(cred, sspi.ASC_REQ_CONNECTION) + authDone, n, err2 := common.UpdateContext(c, otoken, token, nil) + if err2 != nil { + return nil, false, nil, err2 + } + otoken = otoken[:n] + return &ServerContext{sctxt: c}, authDone, otoken, nil +} + +// Release free up resources associated with server context c. +func (c *ServerContext) Release() error { + if c == nil { + return nil + } + return c.sctxt.Release() +} + +// Expiry returns c expiry time. +func (c *ServerContext) Expiry() time.Time { + return c.sctxt.Expiry() +} + +// Update advances server part of Negotiate negotiation c. It uses +// token received from the client and returns true if server part +// of authentication is complete. It also returns new token to be +// sent to the client. +func (c *ServerContext) Update(token []byte) (authCompleted bool, outputToken []byte, err error) { + pkgInfo, err := GetPackageInfo() + if err != nil { + return false, nil, err + } + otoken := make([]byte, pkgInfo.MaxToken) + authDone, n, err2 := common.UpdateContext(c.sctxt, otoken, token, nil) + if err2 != nil { + return false, nil, err2 + } + if n == 0 && !authDone { + return false, nil, errors.New("negotiate token should not be empty") + } + otoken = otoken[:n] + return authDone, otoken, nil +} + +const _SECPKG_ATTR_NATIVE_NAMES = 13 + +type _SecPkgContext_NativeNames struct { + ClientName *uint16 + ServerName *uint16 +} + +// GetUsername returns the username corresponding to the authenticated client +func (c *ServerContext) GetUsername() (string, error) { + var ns _SecPkgContext_NativeNames + ret := sspi.QueryContextAttributes(c.sctxt.Handle, _SECPKG_ATTR_NATIVE_NAMES, (*byte)(unsafe.Pointer(&ns))) + if ret != sspi.SEC_E_OK { + return "", ret + } + sspi.FreeContextBuffer((*byte)(unsafe.Pointer(ns.ServerName))) + defer sspi.FreeContextBuffer((*byte)(unsafe.Pointer(ns.ClientName))) + return syscall.UTF16ToString((*[2 << 20]uint16)(unsafe.Pointer(ns.ClientName))[:]), nil +} + +// ImpersonateUser changes current OS thread user. New user is +// the user as specified by client credentials. +func (c *ServerContext) ImpersonateUser() error { + return c.sctxt.ImpersonateUser() +} + +// RevertToSelf stops impersonation. It changes current OS thread +// user to what it was before ImpersonateUser was executed. +func (c *ServerContext) RevertToSelf() error { + return c.sctxt.RevertToSelf() +} + +// Sizes queries the server context for the sizes used in per-message +// functions. It returns the maximum token size used in authentication +// exchanges, the maximum signature size, the preferred integral size of +// messages, the size of any security trailer, and any error. +func (c *ServerContext) Sizes() (uint32, uint32, uint32, uint32, error) { + return c.sctxt.Sizes() +} + +// MakeSignature uses the established server context to create a signature +// for the given message using the provided quality of protection flags and +// sequence number. It returns the signature token in addition to any error. +func (c *ServerContext) MakeSignature(msg []byte, qop, seqno uint32) ([]byte, error) { + return common.MakeSignature(c.sctxt, msg, qop, seqno) +} + +// VerifySignature uses the established server context and signature token +// to check that the provided message hasn't been tampered or received out +// of sequence. It returns any quality of protection flags and any error +// that occurred. +func (c *ServerContext) VerifySignature(msg, token []byte, seqno uint32) (uint32, error) { + return common.VerifySignature(c.sctxt, msg, token, seqno) +} + +// EncryptMessage uses the established server context to encrypt a message +// using the provided quality of protection flags and sequence number. +// It returns the signature token in addition to any error. +// IMPORTANT: the input msg parameter is updated in place by the low-level windows api +// so must be copied if the initial content should not be modified. +func (c *ServerContext) EncryptMessage(msg []byte, qop, seqno uint32) ([]byte, error) { + return common.EncryptMessage(c.sctxt, msg, qop, seqno) +} + +// DecryptMessage uses the established server context to decrypt a message +// using the provided sequence number. +// It returns the quality of protection flag and the decrypted message in addition to any error. +func (c *ServerContext) DecryptMessage(msg []byte, seqno uint32) (uint32, []byte, error) { + return common.DecryptMessage(c.sctxt, msg, seqno) +} diff --git a/vendor/github.com/alexbrainman/sspi/sspi.go b/vendor/github.com/alexbrainman/sspi/sspi.go new file mode 100644 index 00000000..04f20b75 --- /dev/null +++ b/vendor/github.com/alexbrainman/sspi/sspi.go @@ -0,0 +1,226 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package sspi + +import ( + "fmt" + "syscall" + "time" + "unsafe" +) + +// TODO: add documentation + +type PackageInfo struct { + Capabilities uint32 + Version uint16 + RPCID uint16 + MaxToken uint32 + Name string + Comment string +} + +func QueryPackageInfo(pkgname string) (*PackageInfo, error) { + name, err := syscall.UTF16PtrFromString(pkgname) + if err != nil { + return nil, err + } + var pi *SecPkgInfo + ret := QuerySecurityPackageInfo(name, &pi) + if ret != SEC_E_OK { + return nil, ret + } + defer FreeContextBuffer((*byte)(unsafe.Pointer(pi))) + + return &PackageInfo{ + Capabilities: pi.Capabilities, + Version: pi.Version, + RPCID: pi.RPCID, + MaxToken: pi.MaxToken, + Name: syscall.UTF16ToString((*[2 << 12]uint16)(unsafe.Pointer(pi.Name))[:]), + Comment: syscall.UTF16ToString((*[2 << 12]uint16)(unsafe.Pointer(pi.Comment))[:]), + }, nil +} + +type Credentials struct { + Handle CredHandle + expiry syscall.Filetime +} + +// AcquireCredentials calls the windows AcquireCredentialsHandle function and +// returns Credentials containing a security handle that can be used for +// InitializeSecurityContext or AcceptSecurityContext operations. +// As a special case, passing an empty string as the principal parameter will +// pass a null string to the underlying function. +func AcquireCredentials(principal string, pkgname string, creduse uint32, authdata *byte) (*Credentials, error) { + var principalName *uint16 + if principal != "" { + var err error + principalName, err = syscall.UTF16PtrFromString(principal) + if err != nil { + return nil, err + } + } + name, err := syscall.UTF16PtrFromString(pkgname) + if err != nil { + return nil, err + } + var c Credentials + ret := AcquireCredentialsHandle(principalName, name, creduse, nil, authdata, 0, 0, &c.Handle, &c.expiry) + if ret != SEC_E_OK { + return nil, ret + } + return &c, nil +} + +func (c *Credentials) Release() error { + if c == nil { + return nil + } + ret := FreeCredentialsHandle(&c.Handle) + if ret != SEC_E_OK { + return ret + } + return nil +} + +func (c *Credentials) Expiry() time.Time { + return time.Unix(0, c.expiry.Nanoseconds()) +} + +// TODO: add functions to display and manage RequestedFlags and EstablishedFlags fields. +// TODO: maybe get rid of RequestedFlags and EstablishedFlags fields, and replace them with input parameter for New...Context and return value of Update (instead of current bool parameter). + +type updateFunc func(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno + +type Context struct { + Cred *Credentials + Handle *CtxtHandle + handle CtxtHandle + updFn updateFunc + expiry syscall.Filetime + RequestedFlags uint32 + EstablishedFlags uint32 +} + +func NewClientContext(cred *Credentials, flags uint32) *Context { + return &Context{ + Cred: cred, + updFn: initialize, + RequestedFlags: flags, + } +} + +func NewServerContext(cred *Credentials, flags uint32) *Context { + return &Context{ + Cred: cred, + updFn: accept, + RequestedFlags: flags, + } +} + +func initialize(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno { + return InitializeSecurityContext(&c.Cred.Handle, h, targname, c.RequestedFlags, + 0, SECURITY_NATIVE_DREP, in, 0, newh, out, &c.EstablishedFlags, &c.expiry) +} + +func accept(c *Context, targname *uint16, h, newh *CtxtHandle, out, in *SecBufferDesc) syscall.Errno { + return AcceptSecurityContext(&c.Cred.Handle, h, in, c.RequestedFlags, + SECURITY_NATIVE_DREP, newh, out, &c.EstablishedFlags, &c.expiry) +} + +func (c *Context) Update(targname *uint16, out, in *SecBufferDesc) syscall.Errno { + h := c.Handle + if c.Handle == nil { + c.Handle = &c.handle + } + return c.updFn(c, targname, h, c.Handle, out, in) +} + +func (c *Context) Release() error { + if c == nil { + return nil + } + ret := DeleteSecurityContext(c.Handle) + if ret != SEC_E_OK { + return ret + } + return nil +} + +func (c *Context) Expiry() time.Time { + return time.Unix(0, c.expiry.Nanoseconds()) +} + +// TODO: add comment to function doco that this "impersonation" is applied to current OS thread. +func (c *Context) ImpersonateUser() error { + ret := ImpersonateSecurityContext(c.Handle) + if ret != SEC_E_OK { + return ret + } + return nil +} + +func (c *Context) RevertToSelf() error { + ret := RevertSecurityContext(c.Handle) + if ret != SEC_E_OK { + return ret + } + return nil +} + +// Sizes queries the context for the sizes used in per-message functions. +// It returns the maximum token size used in authentication exchanges, the +// maximum signature size, the preferred integral size of messages, the +// size of any security trailer, and any error. +func (c *Context) Sizes() (uint32, uint32, uint32, uint32, error) { + var s _SecPkgContext_Sizes + ret := QueryContextAttributes(c.Handle, _SECPKG_ATTR_SIZES, (*byte)(unsafe.Pointer(&s))) + if ret != SEC_E_OK { + return 0, 0, 0, 0, ret + } + return s.MaxToken, s.MaxSignature, s.BlockSize, s.SecurityTrailer, nil +} + +// VerifyFlags determines if all flags used to construct the context +// were honored (see NewClientContext). It should be called after c.Update. +func (c *Context) VerifyFlags() error { + return c.VerifySelectiveFlags(c.RequestedFlags) +} + +// VerifySelectiveFlags determines if the given flags were honored (see NewClientContext). +// It should be called after c.Update. +func (c *Context) VerifySelectiveFlags(flags uint32) error { + if valid, missing, extra := verifySelectiveFlags(flags, c.RequestedFlags); !valid { + return fmt.Errorf("sspi: invalid flags check: desired=%b requested=%b missing=%b extra=%b", flags, c.RequestedFlags, missing, extra) + } + if valid, missing, extra := verifySelectiveFlags(flags, c.EstablishedFlags); !valid { + return fmt.Errorf("sspi: invalid flags: desired=%b established=%b missing=%b extra=%b", flags, c.EstablishedFlags, missing, extra) + } + return nil +} + +// verifySelectiveFlags determines if all bits requested in flags are set in establishedFlags. +// missing represents the bits set in flags that are not set in establishedFlags. +// extra represents the bits set in establishedFlags that are not set in flags. +// valid is true and missing is zero when establishedFlags has all of the requested flags. +func verifySelectiveFlags(flags, establishedFlags uint32) (valid bool, missing, extra uint32) { + missing = flags&establishedFlags ^ flags + extra = flags | establishedFlags ^ flags + valid = missing == 0 + return valid, missing, extra +} + +// NewSecBufferDesc returns an initialized SecBufferDesc describing the +// provided SecBuffer. +func NewSecBufferDesc(b []SecBuffer) *SecBufferDesc { + return &SecBufferDesc{ + Version: SECBUFFER_VERSION, + BuffersCount: uint32(len(b)), + Buffers: &b[0], + } +} diff --git a/vendor/github.com/alexbrainman/sspi/syscall.go b/vendor/github.com/alexbrainman/sspi/syscall.go new file mode 100644 index 00000000..04660df2 --- /dev/null +++ b/vendor/github.com/alexbrainman/sspi/syscall.go @@ -0,0 +1,174 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package sspi + +import ( + "syscall" +) + +const ( + SEC_E_OK = syscall.Errno(0) + + SEC_I_COMPLETE_AND_CONTINUE = syscall.Errno(590612) + SEC_I_COMPLETE_NEEDED = syscall.Errno(590611) + SEC_I_CONTINUE_NEEDED = syscall.Errno(590610) + + SEC_E_LOGON_DENIED = syscall.Errno(0x8009030c) + SEC_E_CONTEXT_EXPIRED = syscall.Errno(0x80090317) // not sure if the value is valid + SEC_E_INCOMPLETE_MESSAGE = syscall.Errno(0x80090318) + + NTLMSP_NAME = "NTLM" + MICROSOFT_KERBEROS_NAME = "Kerberos" + NEGOSSP_NAME = "Negotiate" + UNISP_NAME = "Microsoft Unified Security Protocol Provider" + + _SECPKG_ATTR_SIZES = 0 + _SECPKG_ATTR_NAMES = 1 + _SECPKG_ATTR_LIFESPAN = 2 + _SECPKG_ATTR_DCE_INFO = 3 + _SECPKG_ATTR_STREAM_SIZES = 4 + _SECPKG_ATTR_KEY_INFO = 5 + _SECPKG_ATTR_AUTHORITY = 6 + _SECPKG_ATTR_PROTO_INFO = 7 + _SECPKG_ATTR_PASSWORD_EXPIRY = 8 + _SECPKG_ATTR_SESSION_KEY = 9 + _SECPKG_ATTR_PACKAGE_INFO = 10 + _SECPKG_ATTR_USER_FLAGS = 11 + _SECPKG_ATTR_NEGOTIATION_INFO = 12 + _SECPKG_ATTR_NATIVE_NAMES = 13 + _SECPKG_ATTR_FLAGS = 14 +) + +type SecPkgInfo struct { + Capabilities uint32 + Version uint16 + RPCID uint16 + MaxToken uint32 + Name *uint16 + Comment *uint16 +} + +type _SecPkgContext_Sizes struct { + MaxToken uint32 + MaxSignature uint32 + BlockSize uint32 + SecurityTrailer uint32 +} + +//sys QuerySecurityPackageInfo(pkgname *uint16, pkginfo **SecPkgInfo) (ret syscall.Errno) = secur32.QuerySecurityPackageInfoW +//sys FreeContextBuffer(buf *byte) (ret syscall.Errno) = secur32.FreeContextBuffer + +const ( + SECPKG_CRED_INBOUND = 1 + SECPKG_CRED_OUTBOUND = 2 + SECPKG_CRED_BOTH = (SECPKG_CRED_OUTBOUND | SECPKG_CRED_INBOUND) + + SEC_WINNT_AUTH_IDENTITY_UNICODE = 0x2 +) + +type SEC_WINNT_AUTH_IDENTITY struct { + User *uint16 + UserLength uint32 + Domain *uint16 + DomainLength uint32 + Password *uint16 + PasswordLength uint32 + Flags uint32 +} + +type LUID struct { + LowPart uint32 + HighPart int32 +} + +type CredHandle struct { + Lower uintptr + Upper uintptr +} + +//sys AcquireCredentialsHandle(principal *uint16, pkgname *uint16, creduse uint32, logonid *LUID, authdata *byte, getkeyfn uintptr, getkeyarg uintptr, handle *CredHandle, expiry *syscall.Filetime) (ret syscall.Errno) = secur32.AcquireCredentialsHandleW +//sys FreeCredentialsHandle(handle *CredHandle) (ret syscall.Errno) = secur32.FreeCredentialsHandle + +const ( + SECURITY_NATIVE_DREP = 16 + + SECBUFFER_DATA = 1 + SECBUFFER_TOKEN = 2 + SECBUFFER_PKG_PARAMS = 3 + SECBUFFER_MISSING = 4 + SECBUFFER_EXTRA = 5 + SECBUFFER_STREAM_TRAILER = 6 + SECBUFFER_STREAM_HEADER = 7 + SECBUFFER_PADDING = 9 + SECBUFFER_STREAM = 10 + SECBUFFER_READONLY = 0x80000000 + SECBUFFER_ATTRMASK = 0xf0000000 + SECBUFFER_VERSION = 0 + SECBUFFER_EMPTY = 0 + + ISC_REQ_DELEGATE = 1 + ISC_REQ_MUTUAL_AUTH = 2 + ISC_REQ_REPLAY_DETECT = 4 + ISC_REQ_SEQUENCE_DETECT = 8 + ISC_REQ_CONFIDENTIALITY = 16 + ISC_REQ_USE_SESSION_KEY = 32 + ISC_REQ_PROMPT_FOR_CREDS = 64 + ISC_REQ_USE_SUPPLIED_CREDS = 128 + ISC_REQ_ALLOCATE_MEMORY = 256 + ISC_REQ_USE_DCE_STYLE = 512 + ISC_REQ_DATAGRAM = 1024 + ISC_REQ_CONNECTION = 2048 + ISC_REQ_EXTENDED_ERROR = 16384 + ISC_REQ_STREAM = 32768 + ISC_REQ_INTEGRITY = 65536 + ISC_REQ_MANUAL_CRED_VALIDATION = 524288 + ISC_REQ_HTTP = 268435456 + + ASC_REQ_DELEGATE = 1 + ASC_REQ_MUTUAL_AUTH = 2 + ASC_REQ_REPLAY_DETECT = 4 + ASC_REQ_SEQUENCE_DETECT = 8 + ASC_REQ_CONFIDENTIALITY = 16 + ASC_REQ_USE_SESSION_KEY = 32 + ASC_REQ_ALLOCATE_MEMORY = 256 + ASC_REQ_USE_DCE_STYLE = 512 + ASC_REQ_DATAGRAM = 1024 + ASC_REQ_CONNECTION = 2048 + ASC_REQ_EXTENDED_ERROR = 32768 + ASC_REQ_STREAM = 65536 + ASC_REQ_INTEGRITY = 131072 +) + +type CtxtHandle struct { + Lower uintptr + Upper uintptr +} + +type SecBuffer struct { + BufferSize uint32 + BufferType uint32 + Buffer *byte +} + +type SecBufferDesc struct { + Version uint32 + BuffersCount uint32 + Buffers *SecBuffer +} + +//sys InitializeSecurityContext(credential *CredHandle, context *CtxtHandle, targname *uint16, contextreq uint32, reserved1 uint32, targdatarep uint32, input *SecBufferDesc, reserved2 uint32, newcontext *CtxtHandle, output *SecBufferDesc, contextattr *uint32, expiry *syscall.Filetime) (ret syscall.Errno) = secur32.InitializeSecurityContextW +//sys AcceptSecurityContext(credential *CredHandle, context *CtxtHandle, input *SecBufferDesc, contextreq uint32, targdatarep uint32, newcontext *CtxtHandle, output *SecBufferDesc, contextattr *uint32, expiry *syscall.Filetime) (ret syscall.Errno) = secur32.AcceptSecurityContext +//sys CompleteAuthToken(context *CtxtHandle, token *SecBufferDesc) (ret syscall.Errno) = secur32.CompleteAuthToken +//sys DeleteSecurityContext(context *CtxtHandle) (ret syscall.Errno) = secur32.DeleteSecurityContext +//sys ImpersonateSecurityContext(context *CtxtHandle) (ret syscall.Errno) = secur32.ImpersonateSecurityContext +//sys RevertSecurityContext(context *CtxtHandle) (ret syscall.Errno) = secur32.RevertSecurityContext +//sys QueryContextAttributes(context *CtxtHandle, attribute uint32, buf *byte) (ret syscall.Errno) = secur32.QueryContextAttributesW +//sys EncryptMessage(context *CtxtHandle, qop uint32, message *SecBufferDesc, messageseqno uint32) (ret syscall.Errno) = secur32.EncryptMessage +//sys DecryptMessage(context *CtxtHandle, message *SecBufferDesc, messageseqno uint32, qop *uint32) (ret syscall.Errno) = secur32.DecryptMessage +//sys ApplyControlToken(context *CtxtHandle, input *SecBufferDesc) (ret syscall.Errno) = secur32.ApplyControlToken +//sys MakeSignature(context *CtxtHandle, qop uint32, message *SecBufferDesc, messageseqno uint32) (ret syscall.Errno) = secur32.MakeSignature +//sys VerifySignature(context *CtxtHandle, message *SecBufferDesc, messageseqno uint32, qop *uint32) (ret syscall.Errno) = secur32.VerifySignature diff --git a/vendor/github.com/alexbrainman/sspi/zsyscall_windows.go b/vendor/github.com/alexbrainman/sspi/zsyscall_windows.go new file mode 100644 index 00000000..55e82099 --- /dev/null +++ b/vendor/github.com/alexbrainman/sspi/zsyscall_windows.go @@ -0,0 +1,152 @@ +// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT + +package sspi + +import ( + "syscall" + "unsafe" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + modsecur32 = syscall.NewLazyDLL("secur32.dll") + + procQuerySecurityPackageInfoW = modsecur32.NewProc("QuerySecurityPackageInfoW") + procFreeContextBuffer = modsecur32.NewProc("FreeContextBuffer") + procAcquireCredentialsHandleW = modsecur32.NewProc("AcquireCredentialsHandleW") + procFreeCredentialsHandle = modsecur32.NewProc("FreeCredentialsHandle") + procInitializeSecurityContextW = modsecur32.NewProc("InitializeSecurityContextW") + procAcceptSecurityContext = modsecur32.NewProc("AcceptSecurityContext") + procCompleteAuthToken = modsecur32.NewProc("CompleteAuthToken") + procDeleteSecurityContext = modsecur32.NewProc("DeleteSecurityContext") + procImpersonateSecurityContext = modsecur32.NewProc("ImpersonateSecurityContext") + procRevertSecurityContext = modsecur32.NewProc("RevertSecurityContext") + procQueryContextAttributesW = modsecur32.NewProc("QueryContextAttributesW") + procEncryptMessage = modsecur32.NewProc("EncryptMessage") + procDecryptMessage = modsecur32.NewProc("DecryptMessage") + procApplyControlToken = modsecur32.NewProc("ApplyControlToken") + procMakeSignature = modsecur32.NewProc("MakeSignature") + procVerifySignature = modsecur32.NewProc("VerifySignature") +) + +func QuerySecurityPackageInfo(pkgname *uint16, pkginfo **SecPkgInfo) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall(procQuerySecurityPackageInfoW.Addr(), 2, uintptr(unsafe.Pointer(pkgname)), uintptr(unsafe.Pointer(pkginfo)), 0) + ret = syscall.Errno(r0) + return +} + +func FreeContextBuffer(buf *byte) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall(procFreeContextBuffer.Addr(), 1, uintptr(unsafe.Pointer(buf)), 0, 0) + ret = syscall.Errno(r0) + return +} + +func AcquireCredentialsHandle(principal *uint16, pkgname *uint16, creduse uint32, logonid *LUID, authdata *byte, getkeyfn uintptr, getkeyarg uintptr, handle *CredHandle, expiry *syscall.Filetime) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall9(procAcquireCredentialsHandleW.Addr(), 9, uintptr(unsafe.Pointer(principal)), uintptr(unsafe.Pointer(pkgname)), uintptr(creduse), uintptr(unsafe.Pointer(logonid)), uintptr(unsafe.Pointer(authdata)), uintptr(getkeyfn), uintptr(getkeyarg), uintptr(unsafe.Pointer(handle)), uintptr(unsafe.Pointer(expiry))) + ret = syscall.Errno(r0) + return +} + +func FreeCredentialsHandle(handle *CredHandle) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall(procFreeCredentialsHandle.Addr(), 1, uintptr(unsafe.Pointer(handle)), 0, 0) + ret = syscall.Errno(r0) + return +} + +func InitializeSecurityContext(credential *CredHandle, context *CtxtHandle, targname *uint16, contextreq uint32, reserved1 uint32, targdatarep uint32, input *SecBufferDesc, reserved2 uint32, newcontext *CtxtHandle, output *SecBufferDesc, contextattr *uint32, expiry *syscall.Filetime) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall12(procInitializeSecurityContextW.Addr(), 12, uintptr(unsafe.Pointer(credential)), uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(targname)), uintptr(contextreq), uintptr(reserved1), uintptr(targdatarep), uintptr(unsafe.Pointer(input)), uintptr(reserved2), uintptr(unsafe.Pointer(newcontext)), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(contextattr)), uintptr(unsafe.Pointer(expiry))) + ret = syscall.Errno(r0) + return +} + +func AcceptSecurityContext(credential *CredHandle, context *CtxtHandle, input *SecBufferDesc, contextreq uint32, targdatarep uint32, newcontext *CtxtHandle, output *SecBufferDesc, contextattr *uint32, expiry *syscall.Filetime) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall9(procAcceptSecurityContext.Addr(), 9, uintptr(unsafe.Pointer(credential)), uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(input)), uintptr(contextreq), uintptr(targdatarep), uintptr(unsafe.Pointer(newcontext)), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(contextattr)), uintptr(unsafe.Pointer(expiry))) + ret = syscall.Errno(r0) + return +} + +func CompleteAuthToken(context *CtxtHandle, token *SecBufferDesc) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall(procCompleteAuthToken.Addr(), 2, uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(token)), 0) + ret = syscall.Errno(r0) + return +} + +func DeleteSecurityContext(context *CtxtHandle) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall(procDeleteSecurityContext.Addr(), 1, uintptr(unsafe.Pointer(context)), 0, 0) + ret = syscall.Errno(r0) + return +} + +func ImpersonateSecurityContext(context *CtxtHandle) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall(procImpersonateSecurityContext.Addr(), 1, uintptr(unsafe.Pointer(context)), 0, 0) + ret = syscall.Errno(r0) + return +} + +func RevertSecurityContext(context *CtxtHandle) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall(procRevertSecurityContext.Addr(), 1, uintptr(unsafe.Pointer(context)), 0, 0) + ret = syscall.Errno(r0) + return +} + +func QueryContextAttributes(context *CtxtHandle, attribute uint32, buf *byte) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall(procQueryContextAttributesW.Addr(), 3, uintptr(unsafe.Pointer(context)), uintptr(attribute), uintptr(unsafe.Pointer(buf))) + ret = syscall.Errno(r0) + return +} + +func EncryptMessage(context *CtxtHandle, qop uint32, message *SecBufferDesc, messageseqno uint32) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall6(procEncryptMessage.Addr(), 4, uintptr(unsafe.Pointer(context)), uintptr(qop), uintptr(unsafe.Pointer(message)), uintptr(messageseqno), 0, 0) + ret = syscall.Errno(r0) + return +} + +func DecryptMessage(context *CtxtHandle, message *SecBufferDesc, messageseqno uint32, qop *uint32) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall6(procDecryptMessage.Addr(), 4, uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(message)), uintptr(messageseqno), uintptr(unsafe.Pointer(qop)), 0, 0) + ret = syscall.Errno(r0) + return +} + +func ApplyControlToken(context *CtxtHandle, input *SecBufferDesc) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall(procApplyControlToken.Addr(), 2, uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(input)), 0) + ret = syscall.Errno(r0) + return +} + +func MakeSignature(context *CtxtHandle, qop uint32, message *SecBufferDesc, messageseqno uint32) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall6(procMakeSignature.Addr(), 4, uintptr(unsafe.Pointer(context)), uintptr(qop), uintptr(unsafe.Pointer(message)), uintptr(messageseqno), 0, 0) + ret = syscall.Errno(r0) + return +} + +func VerifySignature(context *CtxtHandle, message *SecBufferDesc, messageseqno uint32, qop *uint32) (ret syscall.Errno) { + r0, _, _ := syscall.Syscall6(procVerifySignature.Addr(), 4, uintptr(unsafe.Pointer(context)), uintptr(unsafe.Pointer(message)), uintptr(messageseqno), uintptr(unsafe.Pointer(qop)), 0, 0) + ret = syscall.Errno(r0) + return +} diff --git a/vendor/github.com/bits-and-blooms/bitset/.gitignore b/vendor/github.com/bits-and-blooms/bitset/.gitignore new file mode 100644 index 00000000..5c204d28 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/.gitignore @@ -0,0 +1,26 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +target diff --git a/vendor/github.com/bits-and-blooms/bitset/.travis.yml b/vendor/github.com/bits-and-blooms/bitset/.travis.yml new file mode 100644 index 00000000..094aa5ce --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/.travis.yml @@ -0,0 +1,37 @@ +language: go + +sudo: false + +branches: + except: + - release + +branches: + only: + - master + - travis + +go: + - "1.11.x" + - tip + +matrix: + allow_failures: + - go: tip + +before_install: + - if [ -n "$GH_USER" ]; then git config --global github.user ${GH_USER}; fi; + - if [ -n "$GH_TOKEN" ]; then git config --global github.token ${GH_TOKEN}; fi; + - go get github.com/mattn/goveralls + +before_script: + - make deps + +script: + - make qa + +after_failure: + - cat ./target/test/report.xml + +after_success: + - if [ "$TRAVIS_GO_VERSION" = "1.11.1" ]; then $HOME/gopath/bin/goveralls -covermode=count -coverprofile=target/report/coverage.out -service=travis-ci; fi; diff --git a/vendor/github.com/bits-and-blooms/bitset/LICENSE b/vendor/github.com/bits-and-blooms/bitset/LICENSE new file mode 100644 index 00000000..59cab8a9 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2014 Will Fitzgerald. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/bits-and-blooms/bitset/README.md b/vendor/github.com/bits-and-blooms/bitset/README.md new file mode 100644 index 00000000..fe7bca65 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/README.md @@ -0,0 +1,159 @@ +# bitset + +*Go language library to map between non-negative integers and boolean values* + +[![Test](https://github.com/bits-and-blooms/bitset/workflows/Test/badge.svg)](https://github.com/willf/bitset/actions?query=workflow%3ATest) +[![Go Report Card](https://goreportcard.com/badge/github.com/willf/bitset)](https://goreportcard.com/report/github.com/willf/bitset) +[![PkgGoDev](https://pkg.go.dev/badge/github.com/bits-and-blooms/bitset?tab=doc)](https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc) + + +This library is part of the [awesome go collection](https://github.com/avelino/awesome-go). It is used in production by several important systems: + +* [beego](https://github.com/beego/beego) +* [CubeFS](https://github.com/cubefs/cubefs) +* [Amazon EKS Distro](https://github.com/aws/eks-distro) +* [sourcegraph](https://github.com/sourcegraph/sourcegraph) +* [torrent](https://github.com/anacrolix/torrent) + + +## Description + +Package bitset implements bitsets, a mapping between non-negative integers and boolean values. +It should be more efficient than map[uint] bool. + +It provides methods for setting, clearing, flipping, and testing individual integers. + +But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits. + +BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used. + +Many of the methods, including Set, Clear, and Flip, return a BitSet pointer, which allows for chaining. + +### Example use: + +```go +package main + +import ( + "fmt" + "math/rand" + + "github.com/bits-and-blooms/bitset" +) + +func main() { + fmt.Printf("Hello from BitSet!\n") + var b bitset.BitSet + // play some Go Fish + for i := 0; i < 100; i++ { + card1 := uint(rand.Intn(52)) + card2 := uint(rand.Intn(52)) + b.Set(card1) + if b.Test(card2) { + fmt.Println("Go Fish!") + } + b.Clear(card1) + } + + // Chaining + b.Set(10).Set(11) + + for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) { + fmt.Println("The following bit is set:", i) + } + if b.Intersection(bitset.New(100).Set(10)).Count() == 1 { + fmt.Println("Intersection works.") + } else { + fmt.Println("Intersection doesn't work???") + } +} +``` + + +Package documentation is at: https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc + +## Serialization + + +You may serialize a bitset safely and portably to a stream +of bytes as follows: +```Go + const length = 9585 + const oneEvery = 97 + bs := bitset.New(length) + // Add some bits + for i := uint(0); i < length; i += oneEvery { + bs = bs.Set(i) + } + + var buf bytes.Buffer + n, err := bs.WriteTo(&buf) + if err != nil { + // failure + } + // Here n == buf.Len() +``` +You can later deserialize the result as follows: + +```Go + // Read back from buf + bs = bitset.New() + n, err = bs.ReadFrom(&buf) + if err != nil { + // error + } + // n is the number of bytes read +``` + +The `ReadFrom` function attempts to read the data into the existing +BitSet instance, to minimize memory allocations. + + +*Performance tip*: +When reading and writing to a file or a network connection, you may get better performance by +wrapping your streams with `bufio` instances. + +E.g., +```Go + f, err := os.Create("myfile") + w := bufio.NewWriter(f) +``` +```Go + f, err := os.Open("myfile") + r := bufio.NewReader(f) +``` + +## Memory Usage + +The memory usage of a bitset using `N` bits is at least `N/8` bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](http://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring). + +The `roaring` library allows you to go back and forth between compressed Roaring bitmaps and the conventional bitset instances: +```Go + mybitset := roaringbitmap.ToBitSet() + newroaringbitmap := roaring.FromBitSet(mybitset) +``` + + +## Implementation Note + +Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed. + +It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `uint64`). If so, the version will be bumped. + +## Installation + +```bash +go get github.com/bits-and-blooms/bitset +``` + +## Contributing + +If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)") + +## Running all tests + +Before committing the code, please check if it passes tests, has adequate coverage, etc. +```bash +go test +go test -cover +``` diff --git a/vendor/github.com/bits-and-blooms/bitset/SECURITY.md b/vendor/github.com/bits-and-blooms/bitset/SECURITY.md new file mode 100644 index 00000000..f888420c --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/SECURITY.md @@ -0,0 +1,5 @@ +# Security Policy + +## Reporting a Vulnerability + +You can report privately a vulnerability by email at daniel@lemire.me (current maintainer). diff --git a/vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml b/vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml new file mode 100644 index 00000000..f9b29591 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/azure-pipelines.yml @@ -0,0 +1,39 @@ +# Go +# Build your Go project. +# Add steps that test, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/languages/go + +trigger: +- master + +pool: + vmImage: 'Ubuntu-16.04' + +variables: + GOBIN: '$(GOPATH)/bin' # Go binaries path + GOROOT: '/usr/local/go1.11' # Go installation path + GOPATH: '$(system.defaultWorkingDirectory)/gopath' # Go workspace path + modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' # Path to the module's code + +steps: +- script: | + mkdir -p '$(GOBIN)' + mkdir -p '$(GOPATH)/pkg' + mkdir -p '$(modulePath)' + shopt -s extglob + shopt -s dotglob + mv !(gopath) '$(modulePath)' + echo '##vso[task.prependpath]$(GOBIN)' + echo '##vso[task.prependpath]$(GOROOT)/bin' + displayName: 'Set up the Go workspace' + +- script: | + go version + go get -v -t -d ./... + if [ -f Gopkg.toml ]; then + curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh + dep ensure + fi + go build -v . + workingDirectory: '$(modulePath)' + displayName: 'Get dependencies, then build' diff --git a/vendor/github.com/bits-and-blooms/bitset/bitset.go b/vendor/github.com/bits-and-blooms/bitset/bitset.go new file mode 100644 index 00000000..9f38ed3a --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/bitset.go @@ -0,0 +1,1184 @@ +/* +Package bitset implements bitsets, a mapping +between non-negative integers and boolean values. It should be more +efficient than map[uint] bool. + +It provides methods for setting, clearing, flipping, and testing +individual integers. + +But it also provides set intersection, union, difference, +complement, and symmetric operations, as well as tests to +check whether any, all, or no bits are set, and querying a +bitset's current length and number of positive bits. + +BitSets are expanded to the size of the largest set bit; the +memory allocation is approximately Max bits, where Max is +the largest set bit. BitSets are never shrunk. On creation, +a hint can be given for the number of bits that will be used. + +Many of the methods, including Set,Clear, and Flip, return +a BitSet pointer, which allows for chaining. + +Example use: + + import "bitset" + var b BitSet + b.Set(10).Set(11) + if b.Test(1000) { + b.Clear(1000) + } + if B.Intersection(bitset.New(100).Set(10)).Count() > 1 { + fmt.Println("Intersection works.") + } + +As an alternative to BitSets, one should check out the 'big' package, +which provides a (less set-theoretical) view of bitsets. +*/ +package bitset + +import ( + "bytes" + "encoding/base64" + "encoding/binary" + "encoding/json" + "errors" + "fmt" + "io" + "strconv" +) + +// the wordSize of a bit set +const wordSize = uint(64) + +// the wordSize of a bit set in bytes +const wordBytes = wordSize / 8 + +// log2WordSize is lg(wordSize) +const log2WordSize = uint(6) + +// allBits has every bit set +const allBits uint64 = 0xffffffffffffffff + +// default binary BigEndian +var binaryOrder binary.ByteOrder = binary.BigEndian + +// default json encoding base64.URLEncoding +var base64Encoding = base64.URLEncoding + +// Base64StdEncoding Marshal/Unmarshal BitSet with base64.StdEncoding(Default: base64.URLEncoding) +func Base64StdEncoding() { base64Encoding = base64.StdEncoding } + +// LittleEndian Marshal/Unmarshal Binary as Little Endian(Default: binary.BigEndian) +func LittleEndian() { binaryOrder = binary.LittleEndian } + +// A BitSet is a set of bits. The zero value of a BitSet is an empty set of length 0. +type BitSet struct { + length uint + set []uint64 +} + +// Error is used to distinguish errors (panics) generated in this package. +type Error string + +// safeSet will fixup b.set to be non-nil and return the field value +func (b *BitSet) safeSet() []uint64 { + if b.set == nil { + b.set = make([]uint64, wordsNeeded(0)) + } + return b.set +} + +// SetBitsetFrom fills the bitset with an array of integers without creating a new BitSet instance +func (b *BitSet) SetBitsetFrom(buf []uint64) { + b.length = uint(len(buf)) * 64 + b.set = buf +} + +// From is a constructor used to create a BitSet from an array of words +func From(buf []uint64) *BitSet { + return FromWithLength(uint(len(buf))*64, buf) +} + +// FromWithLength constructs from an array of words and length. +func FromWithLength(len uint, set []uint64) *BitSet { + return &BitSet{len, set} +} + +// Bytes returns the bitset as array of words +func (b *BitSet) Bytes() []uint64 { + return b.set +} + +// wordsNeeded calculates the number of words needed for i bits +func wordsNeeded(i uint) int { + if i > (Cap() - wordSize + 1) { + return int(Cap() >> log2WordSize) + } + return int((i + (wordSize - 1)) >> log2WordSize) +} + +// wordsNeededUnbound calculates the number of words needed for i bits, possibly exceeding the capacity. +// This function is useful if you know that the capacity cannot be exceeded (e.g., you have an existing bitmap). +func wordsNeededUnbound(i uint) int { + return int((i + (wordSize - 1)) >> log2WordSize) +} + +// wordsIndex calculates the index of words in a `uint64` +func wordsIndex(i uint) uint { + return i & (wordSize - 1) +} + +// New creates a new BitSet with a hint that length bits will be required +func New(length uint) (bset *BitSet) { + defer func() { + if r := recover(); r != nil { + bset = &BitSet{ + 0, + make([]uint64, 0), + } + } + }() + + bset = &BitSet{ + length, + make([]uint64, wordsNeeded(length)), + } + + return bset +} + +// Cap returns the total possible capacity, or number of bits +func Cap() uint { + return ^uint(0) +} + +// Len returns the number of bits in the BitSet. +// Note the difference to method Count, see example. +func (b *BitSet) Len() uint { + return b.length +} + +// extendSet adds additional words to incorporate new bits if needed +func (b *BitSet) extendSet(i uint) { + if i >= Cap() { + panic("You are exceeding the capacity") + } + nsize := wordsNeeded(i + 1) + if b.set == nil { + b.set = make([]uint64, nsize) + } else if cap(b.set) >= nsize { + b.set = b.set[:nsize] // fast resize + } else if len(b.set) < nsize { + newset := make([]uint64, nsize, 2*nsize) // increase capacity 2x + copy(newset, b.set) + b.set = newset + } + b.length = i + 1 +} + +// Test whether bit i is set. +func (b *BitSet) Test(i uint) bool { + if i >= b.length { + return false + } + return b.set[i>>log2WordSize]&(1<= Cap(), this function will panic. +// Warning: using a very large value for 'i' +// may lead to a memory shortage and a panic: the caller is responsible +// for providing sensible parameters in line with their memory capacity. +func (b *BitSet) Set(i uint) *BitSet { + if i >= b.length { // if we need more bits, make 'em + b.extendSet(i) + } + b.set[i>>log2WordSize] |= 1 << wordsIndex(i) + return b +} + +// Clear bit i to 0 +func (b *BitSet) Clear(i uint) *BitSet { + if i >= b.length { + return b + } + b.set[i>>log2WordSize] &^= 1 << wordsIndex(i) + return b +} + +// SetTo sets bit i to value. +// If i>= Cap(), this function will panic. +// Warning: using a very large value for 'i' +// may lead to a memory shortage and a panic: the caller is responsible +// for providing sensible parameters in line with their memory capacity. +func (b *BitSet) SetTo(i uint, value bool) *BitSet { + if value { + return b.Set(i) + } + return b.Clear(i) +} + +// Flip bit at i. +// If i>= Cap(), this function will panic. +// Warning: using a very large value for 'i' +// may lead to a memory shortage and a panic: the caller is responsible +// for providing sensible parameters in line with their memory capacity. +func (b *BitSet) Flip(i uint) *BitSet { + if i >= b.length { + return b.Set(i) + } + b.set[i>>log2WordSize] ^= 1 << wordsIndex(i) + return b +} + +// FlipRange bit in [start, end). +// If end>= Cap(), this function will panic. +// Warning: using a very large value for 'end' +// may lead to a memory shortage and a panic: the caller is responsible +// for providing sensible parameters in line with their memory capacity. +func (b *BitSet) FlipRange(start, end uint) *BitSet { + if start >= end { + return b + } + if end-1 >= b.length { // if we need more bits, make 'em + b.extendSet(end - 1) + } + var startWord uint = start >> log2WordSize + var endWord uint = end >> log2WordSize + b.set[startWord] ^= ^(^uint64(0) << wordsIndex(start)) + if endWord > 0 { + // bounds check elimination + data := b.set + _ = data[endWord-1] + for i := startWord; i < endWord; i++ { + data[i] = ^data[i] + } + } + if end&(wordSize-1) != 0 { + b.set[endWord] ^= ^uint64(0) >> wordsIndex(-end) + } + return b +} + +// Shrink shrinks BitSet so that the provided value is the last possible +// set value. It clears all bits > the provided index and reduces the size +// and length of the set. +// +// Note that the parameter value is not the new length in bits: it is the +// maximal value that can be stored in the bitset after the function call. +// The new length in bits is the parameter value + 1. Thus it is not possible +// to use this function to set the length to 0, the minimal value of the length +// after this function call is 1. +// +// A new slice is allocated to store the new bits, so you may see an increase in +// memory usage until the GC runs. Normally this should not be a problem, but if you +// have an extremely large BitSet its important to understand that the old BitSet will +// remain in memory until the GC frees it. +func (b *BitSet) Shrink(lastbitindex uint) *BitSet { + length := lastbitindex + 1 + idx := wordsNeeded(length) + if idx > len(b.set) { + return b + } + shrunk := make([]uint64, idx) + copy(shrunk, b.set[:idx]) + b.set = shrunk + b.length = length + lastWordUsedBits := length % 64 + if lastWordUsedBits != 0 { + b.set[idx-1] &= allBits >> uint64(64-wordsIndex(lastWordUsedBits)) + } + return b +} + +// Compact shrinks BitSet to so that we preserve all set bits, while minimizing +// memory usage. Compact calls Shrink. +func (b *BitSet) Compact() *BitSet { + idx := len(b.set) - 1 + for ; idx >= 0 && b.set[idx] == 0; idx-- { + } + newlength := uint((idx + 1) << log2WordSize) + if newlength >= b.length { + return b // nothing to do + } + if newlength > 0 { + return b.Shrink(newlength - 1) + } + // We preserve one word + return b.Shrink(63) +} + +// InsertAt takes an index which indicates where a bit should be +// inserted. Then it shifts all the bits in the set to the left by 1, starting +// from the given index position, and sets the index position to 0. +// +// Depending on the size of your BitSet, and where you are inserting the new entry, +// this method could be extremely slow and in some cases might cause the entire BitSet +// to be recopied. +func (b *BitSet) InsertAt(idx uint) *BitSet { + insertAtElement := idx >> log2WordSize + + // if length of set is a multiple of wordSize we need to allocate more space first + if b.isLenExactMultiple() { + b.set = append(b.set, uint64(0)) + } + + var i uint + for i = uint(len(b.set) - 1); i > insertAtElement; i-- { + // all elements above the position where we want to insert can simply by shifted + b.set[i] <<= 1 + + // we take the most significant bit of the previous element and set it as + // the least significant bit of the current element + b.set[i] |= (b.set[i-1] & 0x8000000000000000) >> 63 + } + + // generate a mask to extract the data that we need to shift left + // within the element where we insert a bit + dataMask := uint64(1)< 0x40000 { + buffer.WriteString("...") + break + } + buffer.WriteString(strconv.FormatInt(int64(i), 10)) + i, e = b.NextSet(i + 1) + if e { + buffer.WriteString(",") + } + } + buffer.WriteString("}") + return buffer.String() +} + +// DeleteAt deletes the bit at the given index position from +// within the bitset +// All the bits residing on the left of the deleted bit get +// shifted right by 1 +// The running time of this operation may potentially be +// relatively slow, O(length) +func (b *BitSet) DeleteAt(i uint) *BitSet { + // the index of the slice element where we'll delete a bit + deleteAtElement := i >> log2WordSize + + // generate a mask for the data that needs to be shifted right + // within that slice element that gets modified + dataMask := ^((uint64(1) << wordsIndex(i)) - 1) + + // extract the data that we'll shift right from the slice element + data := b.set[deleteAtElement] & dataMask + + // set the masked area to 0 while leaving the rest as it is + b.set[deleteAtElement] &= ^dataMask + + // shift the previously extracted data to the right and then + // set it in the previously masked area + b.set[deleteAtElement] |= (data >> 1) & dataMask + + // loop over all the consecutive slice elements to copy each + // lowest bit into the highest position of the previous element, + // then shift the entire content to the right by 1 + for i := int(deleteAtElement) + 1; i < len(b.set); i++ { + b.set[i-1] |= (b.set[i] & 1) << 63 + b.set[i] >>= 1 + } + + b.length = b.length - 1 + + return b +} + +// NextSet returns the next bit set from the specified index, +// including possibly the current index +// along with an error code (true = valid, false = no set bit found) +// for i,e := v.NextSet(0); e; i,e = v.NextSet(i + 1) {...} +// +// Users concerned with performance may want to use NextSetMany to +// retrieve several values at once. +func (b *BitSet) NextSet(i uint) (uint, bool) { + x := int(i >> log2WordSize) + if x >= len(b.set) { + return 0, false + } + w := b.set[x] + w = w >> wordsIndex(i) + if w != 0 { + return i + trailingZeroes64(w), true + } + x++ + // bounds check elimination in the loop + if x < 0 { + return 0, false + } + for x < len(b.set) { + if b.set[x] != 0 { + return uint(x)*wordSize + trailingZeroes64(b.set[x]), true + } + x++ + + } + return 0, false +} + +// NextSetMany returns many next bit sets from the specified index, +// including possibly the current index and up to cap(buffer). +// If the returned slice has len zero, then no more set bits were found +// +// buffer := make([]uint, 256) // this should be reused +// j := uint(0) +// j, buffer = bitmap.NextSetMany(j, buffer) +// for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j,buffer) { +// for k := range buffer { +// do something with buffer[k] +// } +// j += 1 +// } +// +// It is possible to retrieve all set bits as follow: +// +// indices := make([]uint, bitmap.Count()) +// bitmap.NextSetMany(0, indices) +// +// However if bitmap.Count() is large, it might be preferable to +// use several calls to NextSetMany, for performance reasons. +func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) { + myanswer := buffer + capacity := cap(buffer) + x := int(i >> log2WordSize) + if x >= len(b.set) || capacity == 0 { + return 0, myanswer[:0] + } + skip := wordsIndex(i) + word := b.set[x] >> skip + myanswer = myanswer[:capacity] + size := int(0) + for word != 0 { + r := trailingZeroes64(word) + t := word & ((^word) + 1) + myanswer[size] = r + i + size++ + if size == capacity { + goto End + } + word = word ^ t + } + x++ + for idx, word := range b.set[x:] { + for word != 0 { + r := trailingZeroes64(word) + t := word & ((^word) + 1) + myanswer[size] = r + (uint(x+idx) << 6) + size++ + if size == capacity { + goto End + } + word = word ^ t + } + } +End: + if size > 0 { + return myanswer[size-1], myanswer[:size] + } + return 0, myanswer[:0] +} + +// NextClear returns the next clear bit from the specified index, +// including possibly the current index +// along with an error code (true = valid, false = no bit found i.e. all bits are set) +func (b *BitSet) NextClear(i uint) (uint, bool) { + x := int(i >> log2WordSize) + if x >= len(b.set) { + return 0, false + } + w := b.set[x] + w = w >> wordsIndex(i) + wA := allBits >> wordsIndex(i) + index := i + trailingZeroes64(^w) + if w != wA && index < b.length { + return index, true + } + x++ + // bounds check elimination in the loop + if x < 0 { + return 0, false + } + for x < len(b.set) { + if b.set[x] != allBits { + index = uint(x)*wordSize + trailingZeroes64(^b.set[x]) + if index < b.length { + return index, true + } + } + x++ + } + return 0, false +} + +// ClearAll clears the entire BitSet +func (b *BitSet) ClearAll() *BitSet { + if b != nil && b.set != nil { + for i := range b.set { + b.set[i] = 0 + } + } + return b +} + +// SetAll sets the entire BitSet +func (b *BitSet) SetAll() *BitSet { + if b != nil && b.set != nil { + for i := range b.set { + b.set[i] = allBits + } + + b.cleanLastWord() + } + return b +} + +// wordCount returns the number of words used in a bit set +func (b *BitSet) wordCount() int { + return wordsNeededUnbound(b.length) +} + +// Clone this BitSet +func (b *BitSet) Clone() *BitSet { + c := New(b.length) + if b.set != nil { // Clone should not modify current object + copy(c.set, b.set) + } + return c +} + +// Copy into a destination BitSet using the Go array copy semantics: +// the number of bits copied is the minimum of the number of bits in the current +// BitSet (Len()) and the destination Bitset. +// We return the number of bits copied in the destination BitSet. +func (b *BitSet) Copy(c *BitSet) (count uint) { + if c == nil { + return + } + if b.set != nil { // Copy should not modify current object + copy(c.set, b.set) + } + count = c.length + if b.length < c.length { + count = b.length + } + // Cleaning the last word is needed to keep the invariant that other functions, such as Count, require + // that any bits in the last word that would exceed the length of the bitmask are set to 0. + c.cleanLastWord() + return +} + +// CopyFull copies into a destination BitSet such that the destination is +// identical to the source after the operation, allocating memory if necessary. +func (b *BitSet) CopyFull(c *BitSet) { + if c == nil { + return + } + c.length = b.length + if len(b.set) == 0 { + if c.set != nil { + c.set = c.set[:0] + } + } else { + if cap(c.set) < len(b.set) { + c.set = make([]uint64, len(b.set)) + } else { + c.set = c.set[:len(b.set)] + } + copy(c.set, b.set) + } +} + +// Count (number of set bits). +// Also known as "popcount" or "population count". +func (b *BitSet) Count() uint { + if b != nil && b.set != nil { + return uint(popcntSlice(b.set)) + } + return 0 +} + +// Equal tests the equivalence of two BitSets. +// False if they are of different sizes, otherwise true +// only if all the same bits are set +func (b *BitSet) Equal(c *BitSet) bool { + if c == nil || b == nil { + return c == b + } + if b.length != c.length { + return false + } + if b.length == 0 { // if they have both length == 0, then could have nil set + return true + } + wn := b.wordCount() + // bounds check elimination + if wn <= 0 { + return true + } + _ = b.set[wn-1] + _ = c.set[wn-1] + for p := 0; p < wn; p++ { + if c.set[p] != b.set[p] { + return false + } + } + return true +} + +func panicIfNull(b *BitSet) { + if b == nil { + panic(Error("BitSet must not be null")) + } +} + +// Difference of base set and other set +// This is the BitSet equivalent of &^ (and not) +func (b *BitSet) Difference(compare *BitSet) (result *BitSet) { + panicIfNull(b) + panicIfNull(compare) + result = b.Clone() // clone b (in case b is bigger than compare) + l := compare.wordCount() + if l > b.wordCount() { + l = b.wordCount() + } + for i := 0; i < l; i++ { + result.set[i] = b.set[i] &^ compare.set[i] + } + return +} + +// DifferenceCardinality computes the cardinality of the differnce +func (b *BitSet) DifferenceCardinality(compare *BitSet) uint { + panicIfNull(b) + panicIfNull(compare) + l := compare.wordCount() + if l > b.wordCount() { + l = b.wordCount() + } + cnt := uint64(0) + cnt += popcntMaskSlice(b.set[:l], compare.set[:l]) + cnt += popcntSlice(b.set[l:]) + return uint(cnt) +} + +// InPlaceDifference computes the difference of base set and other set +// This is the BitSet equivalent of &^ (and not) +func (b *BitSet) InPlaceDifference(compare *BitSet) { + panicIfNull(b) + panicIfNull(compare) + l := compare.wordCount() + if l > b.wordCount() { + l = b.wordCount() + } + if l <= 0 { + return + } + // bounds check elimination + data, cmpData := b.set, compare.set + _ = data[l-1] + _ = cmpData[l-1] + for i := 0; i < l; i++ { + data[i] &^= cmpData[i] + } +} + +// Convenience function: return two bitsets ordered by +// increasing length. Note: neither can be nil +func sortByLength(a *BitSet, b *BitSet) (ap *BitSet, bp *BitSet) { + if a.length <= b.length { + ap, bp = a, b + } else { + ap, bp = b, a + } + return +} + +// Intersection of base set and other set +// This is the BitSet equivalent of & (and) +func (b *BitSet) Intersection(compare *BitSet) (result *BitSet) { + panicIfNull(b) + panicIfNull(compare) + b, compare = sortByLength(b, compare) + result = New(b.length) + for i, word := range b.set { + result.set[i] = word & compare.set[i] + } + return +} + +// IntersectionCardinality computes the cardinality of the union +func (b *BitSet) IntersectionCardinality(compare *BitSet) uint { + panicIfNull(b) + panicIfNull(compare) + b, compare = sortByLength(b, compare) + cnt := popcntAndSlice(b.set, compare.set) + return uint(cnt) +} + +// InPlaceIntersection destructively computes the intersection of +// base set and the compare set. +// This is the BitSet equivalent of & (and) +func (b *BitSet) InPlaceIntersection(compare *BitSet) { + panicIfNull(b) + panicIfNull(compare) + l := compare.wordCount() + if l > b.wordCount() { + l = b.wordCount() + } + if l > 0 { + // bounds check elimination + data, cmpData := b.set, compare.set + _ = data[l-1] + _ = cmpData[l-1] + + for i := 0; i < l; i++ { + data[i] &= cmpData[i] + } + } + if l >= 0 { + for i := l; i < len(b.set); i++ { + b.set[i] = 0 + } + } + if compare.length > 0 { + if compare.length-1 >= b.length { + b.extendSet(compare.length - 1) + } + } +} + +// Union of base set and other set +// This is the BitSet equivalent of | (or) +func (b *BitSet) Union(compare *BitSet) (result *BitSet) { + panicIfNull(b) + panicIfNull(compare) + b, compare = sortByLength(b, compare) + result = compare.Clone() + for i, word := range b.set { + result.set[i] = word | compare.set[i] + } + return +} + +// UnionCardinality computes the cardinality of the uniton of the base set +// and the compare set. +func (b *BitSet) UnionCardinality(compare *BitSet) uint { + panicIfNull(b) + panicIfNull(compare) + b, compare = sortByLength(b, compare) + cnt := popcntOrSlice(b.set, compare.set) + if len(compare.set) > len(b.set) { + cnt += popcntSlice(compare.set[len(b.set):]) + } + return uint(cnt) +} + +// InPlaceUnion creates the destructive union of base set and compare set. +// This is the BitSet equivalent of | (or). +func (b *BitSet) InPlaceUnion(compare *BitSet) { + panicIfNull(b) + panicIfNull(compare) + l := compare.wordCount() + if l > b.wordCount() { + l = b.wordCount() + } + if compare.length > 0 && compare.length-1 >= b.length { + b.extendSet(compare.length - 1) + } + if l > 0 { + // bounds check elimination + data, cmpData := b.set, compare.set + _ = data[l-1] + _ = cmpData[l-1] + + for i := 0; i < l; i++ { + data[i] |= cmpData[i] + } + } + if len(compare.set) > l { + for i := l; i < len(compare.set); i++ { + b.set[i] = compare.set[i] + } + } +} + +// SymmetricDifference of base set and other set +// This is the BitSet equivalent of ^ (xor) +func (b *BitSet) SymmetricDifference(compare *BitSet) (result *BitSet) { + panicIfNull(b) + panicIfNull(compare) + b, compare = sortByLength(b, compare) + // compare is bigger, so clone it + result = compare.Clone() + for i, word := range b.set { + result.set[i] = word ^ compare.set[i] + } + return +} + +// SymmetricDifferenceCardinality computes the cardinality of the symmetric difference +func (b *BitSet) SymmetricDifferenceCardinality(compare *BitSet) uint { + panicIfNull(b) + panicIfNull(compare) + b, compare = sortByLength(b, compare) + cnt := popcntXorSlice(b.set, compare.set) + if len(compare.set) > len(b.set) { + cnt += popcntSlice(compare.set[len(b.set):]) + } + return uint(cnt) +} + +// InPlaceSymmetricDifference creates the destructive SymmetricDifference of base set and other set +// This is the BitSet equivalent of ^ (xor) +func (b *BitSet) InPlaceSymmetricDifference(compare *BitSet) { + panicIfNull(b) + panicIfNull(compare) + l := compare.wordCount() + if l > b.wordCount() { + l = b.wordCount() + } + if compare.length > 0 && compare.length-1 >= b.length { + b.extendSet(compare.length - 1) + } + if l > 0 { + // bounds check elimination + data, cmpData := b.set, compare.set + _ = data[l-1] + _ = cmpData[l-1] + for i := 0; i < l; i++ { + data[i] ^= cmpData[i] + } + } + if len(compare.set) > l { + for i := l; i < len(compare.set); i++ { + b.set[i] = compare.set[i] + } + } +} + +// Is the length an exact multiple of word sizes? +func (b *BitSet) isLenExactMultiple() bool { + return wordsIndex(b.length) == 0 +} + +// Clean last word by setting unused bits to 0 +func (b *BitSet) cleanLastWord() { + if !b.isLenExactMultiple() { + b.set[len(b.set)-1] &= allBits >> (wordSize - wordsIndex(b.length)) + } +} + +// Complement computes the (local) complement of a bitset (up to length bits) +func (b *BitSet) Complement() (result *BitSet) { + panicIfNull(b) + result = New(b.length) + for i, word := range b.set { + result.set[i] = ^word + } + result.cleanLastWord() + return +} + +// All returns true if all bits are set, false otherwise. Returns true for +// empty sets. +func (b *BitSet) All() bool { + panicIfNull(b) + return b.Count() == b.length +} + +// None returns true if no bit is set, false otherwise. Returns true for +// empty sets. +func (b *BitSet) None() bool { + panicIfNull(b) + if b != nil && b.set != nil { + for _, word := range b.set { + if word > 0 { + return false + } + } + } + return true +} + +// Any returns true if any bit is set, false otherwise +func (b *BitSet) Any() bool { + panicIfNull(b) + return !b.None() +} + +// IsSuperSet returns true if this is a superset of the other set +func (b *BitSet) IsSuperSet(other *BitSet) bool { + l := other.wordCount() + if b.wordCount() < l { + l = b.wordCount() + } + for i, word := range other.set[:l] { + if b.set[i]&word != word { + return false + } + } + return popcntSlice(other.set[l:]) == 0 +} + +// IsStrictSuperSet returns true if this is a strict superset of the other set +func (b *BitSet) IsStrictSuperSet(other *BitSet) bool { + return b.Count() > other.Count() && b.IsSuperSet(other) +} + +// DumpAsBits dumps a bit set as a string of bits. Following the usual convention in Go, +// the least significant bits are printed last (index 0 is at the end of the string). +func (b *BitSet) DumpAsBits() string { + if b.set == nil { + return "." + } + buffer := bytes.NewBufferString("") + i := len(b.set) - 1 + for ; i >= 0; i-- { + fmt.Fprintf(buffer, "%064b.", b.set[i]) + } + return buffer.String() +} + +// BinaryStorageSize returns the binary storage requirements (see WriteTo) in bytes. +func (b *BitSet) BinaryStorageSize() int { + return int(wordBytes + wordBytes*uint(b.wordCount())) +} + +func readUint64Array(reader io.Reader, data []uint64) error { + length := len(data) + bufferSize := 128 + buffer := make([]byte, bufferSize*int(wordBytes)) + for i := 0; i < length; i += bufferSize { + end := i + bufferSize + if end > length { + end = length + buffer = buffer[:wordBytes*uint(end-i)] + } + chunk := data[i:end] + if _, err := io.ReadFull(reader, buffer); err != nil { + return err + } + for i := range chunk { + chunk[i] = uint64(binaryOrder.Uint64(buffer[8*i:])) + } + } + return nil +} + +func writeUint64Array(writer io.Writer, data []uint64) error { + bufferSize := 128 + buffer := make([]byte, bufferSize*int(wordBytes)) + for i := 0; i < len(data); i += bufferSize { + end := i + bufferSize + if end > len(data) { + end = len(data) + buffer = buffer[:wordBytes*uint(end-i)] + } + chunk := data[i:end] + for i, x := range chunk { + binaryOrder.PutUint64(buffer[8*i:], x) + } + _, err := writer.Write(buffer) + if err != nil { + return err + } + } + return nil +} + +// WriteTo writes a BitSet to a stream. The format is: +// 1. uint64 length +// 2. []uint64 set +// Upon success, the number of bytes written is returned. +// +// Performance: if this function is used to write to a disk or network +// connection, it might be beneficial to wrap the stream in a bufio.Writer. +// E.g., +// +// f, err := os.Create("myfile") +// w := bufio.NewWriter(f) +func (b *BitSet) WriteTo(stream io.Writer) (int64, error) { + length := uint64(b.length) + // Write length + err := binary.Write(stream, binaryOrder, &length) + if err != nil { + // Upon failure, we do not guarantee that we + // return the number of bytes written. + return int64(0), err + } + err = writeUint64Array(stream, b.set[:b.wordCount()]) + if err != nil { + // Upon failure, we do not guarantee that we + // return the number of bytes written. + return int64(wordBytes), err + } + return int64(b.BinaryStorageSize()), nil +} + +// ReadFrom reads a BitSet from a stream written using WriteTo +// The format is: +// 1. uint64 length +// 2. []uint64 set +// Upon success, the number of bytes read is returned. +// If the current BitSet is not large enough to hold the data, +// it is extended. In case of error, the BitSet is either +// left unchanged or made empty if the error occurs too late +// to preserve the content. +// +// Performance: if this function is used to read from a disk or network +// connection, it might be beneficial to wrap the stream in a bufio.Reader. +// E.g., +// +// f, err := os.Open("myfile") +// r := bufio.NewReader(f) +func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) { + var length uint64 + err := binary.Read(stream, binaryOrder, &length) + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return 0, err + } + newlength := uint(length) + + if uint64(newlength) != length { + return 0, errors.New("unmarshalling error: type mismatch") + } + nWords := wordsNeeded(uint(newlength)) + if cap(b.set) >= nWords { + b.set = b.set[:nWords] + } else { + b.set = make([]uint64, nWords) + } + + b.length = newlength + + err = readUint64Array(stream, b.set) + if err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + // We do not want to leave the BitSet partially filled as + // it is error prone. + b.set = b.set[:0] + b.length = 0 + return 0, err + } + + return int64(b.BinaryStorageSize()), nil +} + +// MarshalBinary encodes a BitSet into a binary form and returns the result. +func (b *BitSet) MarshalBinary() ([]byte, error) { + var buf bytes.Buffer + _, err := b.WriteTo(&buf) + if err != nil { + return []byte{}, err + } + + return buf.Bytes(), err +} + +// UnmarshalBinary decodes the binary form generated by MarshalBinary. +func (b *BitSet) UnmarshalBinary(data []byte) error { + buf := bytes.NewReader(data) + _, err := b.ReadFrom(buf) + return err +} + +// MarshalJSON marshals a BitSet as a JSON structure +func (b BitSet) MarshalJSON() ([]byte, error) { + buffer := bytes.NewBuffer(make([]byte, 0, b.BinaryStorageSize())) + _, err := b.WriteTo(buffer) + if err != nil { + return nil, err + } + + // URLEncode all bytes + return json.Marshal(base64Encoding.EncodeToString(buffer.Bytes())) +} + +// UnmarshalJSON unmarshals a BitSet from JSON created using MarshalJSON +func (b *BitSet) UnmarshalJSON(data []byte) error { + // Unmarshal as string + var s string + err := json.Unmarshal(data, &s) + if err != nil { + return err + } + + // URLDecode string + buf, err := base64Encoding.DecodeString(s) + if err != nil { + return err + } + + _, err = b.ReadFrom(bytes.NewReader(buf)) + return err +} + +// Rank returns the nunber of set bits up to and including the index +// that are set in the bitset. +// See https://en.wikipedia.org/wiki/Ranking#Ranking_in_statistics +func (b *BitSet) Rank(index uint) uint { + if index >= b.length { + return b.Count() + } + leftover := (index + 1) & 63 + answer := uint(popcntSlice(b.set[:(index+1)>>6])) + if leftover != 0 { + answer += uint(popcount(b.set[(index+1)>>6] << (64 - leftover))) + } + return answer +} + +// Select returns the index of the jth set bit, where j is the argument. +// The caller is responsible to ensure that 0 <= j < Count(): when j is +// out of range, the function returns the length of the bitset (b.length). +// +// Note that this function differs in convention from the Rank function which +// returns 1 when ranking the smallest value. We follow the conventional +// textbook definition of Select and Rank. +func (b *BitSet) Select(index uint) uint { + leftover := index + for idx, word := range b.set { + w := uint(popcount(word)) + if w > leftover { + return uint(idx)*64 + select64(word, leftover) + } + leftover -= w + } + return b.length +} diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt.go b/vendor/github.com/bits-and-blooms/bitset/popcnt.go new file mode 100644 index 00000000..76577a83 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/popcnt.go @@ -0,0 +1,53 @@ +package bitset + +// bit population count, take from +// https://code.google.com/p/go/issues/detail?id=4988#c11 +// credit: https://code.google.com/u/arnehormann/ +func popcount(x uint64) (n uint64) { + x -= (x >> 1) & 0x5555555555555555 + x = (x>>2)&0x3333333333333333 + x&0x3333333333333333 + x += x >> 4 + x &= 0x0f0f0f0f0f0f0f0f + x *= 0x0101010101010101 + return x >> 56 +} + +func popcntSliceGo(s []uint64) uint64 { + cnt := uint64(0) + for _, x := range s { + cnt += popcount(x) + } + return cnt +} + +func popcntMaskSliceGo(s, m []uint64) uint64 { + cnt := uint64(0) + for i := range s { + cnt += popcount(s[i] &^ m[i]) + } + return cnt +} + +func popcntAndSliceGo(s, m []uint64) uint64 { + cnt := uint64(0) + for i := range s { + cnt += popcount(s[i] & m[i]) + } + return cnt +} + +func popcntOrSliceGo(s, m []uint64) uint64 { + cnt := uint64(0) + for i := range s { + cnt += popcount(s[i] | m[i]) + } + return cnt +} + +func popcntXorSliceGo(s, m []uint64) uint64 { + cnt := uint64(0) + for i := range s { + cnt += popcount(s[i] ^ m[i]) + } + return cnt +} diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt_19.go b/vendor/github.com/bits-and-blooms/bitset/popcnt_19.go new file mode 100644 index 00000000..7855c04b --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/popcnt_19.go @@ -0,0 +1,62 @@ +//go:build go1.9 +// +build go1.9 + +package bitset + +import "math/bits" + +func popcntSlice(s []uint64) uint64 { + var cnt int + for _, x := range s { + cnt += bits.OnesCount64(x) + } + return uint64(cnt) +} + +func popcntMaskSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } + for i := range s { + cnt += bits.OnesCount64(s[i] &^ m[i]) + } + return uint64(cnt) +} + +func popcntAndSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } + for i := range s { + cnt += bits.OnesCount64(s[i] & m[i]) + } + return uint64(cnt) +} + +func popcntOrSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } + for i := range s { + cnt += bits.OnesCount64(s[i] | m[i]) + } + return uint64(cnt) +} + +func popcntXorSlice(s, m []uint64) uint64 { + var cnt int + // this explicit check eliminates a bounds check in the loop + if len(m) < len(s) { + panic("mask slice is too short") + } + for i := range s { + cnt += bits.OnesCount64(s[i] ^ m[i]) + } + return uint64(cnt) +} diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go b/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go new file mode 100644 index 00000000..116e0444 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.go @@ -0,0 +1,68 @@ +//go:build !go1.9 && amd64 && !appengine +// +build !go1.9,amd64,!appengine + +package bitset + +// *** the following functions are defined in popcnt_amd64.s + +//go:noescape + +func hasAsm() bool + +// useAsm is a flag used to select the GO or ASM implementation of the popcnt function +var useAsm = hasAsm() + +//go:noescape + +func popcntSliceAsm(s []uint64) uint64 + +//go:noescape + +func popcntMaskSliceAsm(s, m []uint64) uint64 + +//go:noescape + +func popcntAndSliceAsm(s, m []uint64) uint64 + +//go:noescape + +func popcntOrSliceAsm(s, m []uint64) uint64 + +//go:noescape + +func popcntXorSliceAsm(s, m []uint64) uint64 + +func popcntSlice(s []uint64) uint64 { + if useAsm { + return popcntSliceAsm(s) + } + return popcntSliceGo(s) +} + +func popcntMaskSlice(s, m []uint64) uint64 { + if useAsm { + return popcntMaskSliceAsm(s, m) + } + return popcntMaskSliceGo(s, m) +} + +func popcntAndSlice(s, m []uint64) uint64 { + if useAsm { + return popcntAndSliceAsm(s, m) + } + return popcntAndSliceGo(s, m) +} + +func popcntOrSlice(s, m []uint64) uint64 { + if useAsm { + return popcntOrSliceAsm(s, m) + } + return popcntOrSliceGo(s, m) +} + +func popcntXorSlice(s, m []uint64) uint64 { + if useAsm { + return popcntXorSliceAsm(s, m) + } + return popcntXorSliceGo(s, m) +} diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s b/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s new file mode 100644 index 00000000..666c0dcc --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/popcnt_amd64.s @@ -0,0 +1,104 @@ +// +build !go1.9 +// +build amd64,!appengine + +TEXT ·hasAsm(SB),4,$0-1 +MOVQ $1, AX +CPUID +SHRQ $23, CX +ANDQ $1, CX +MOVB CX, ret+0(FP) +RET + +#define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2 + +TEXT ·popcntSliceAsm(SB),4,$0-32 +XORQ AX, AX +MOVQ s+0(FP), SI +MOVQ s_len+8(FP), CX +TESTQ CX, CX +JZ popcntSliceEnd +popcntSliceLoop: +BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX +ADDQ DX, AX +ADDQ $8, SI +LOOP popcntSliceLoop +popcntSliceEnd: +MOVQ AX, ret+24(FP) +RET + +TEXT ·popcntMaskSliceAsm(SB),4,$0-56 +XORQ AX, AX +MOVQ s+0(FP), SI +MOVQ s_len+8(FP), CX +TESTQ CX, CX +JZ popcntMaskSliceEnd +MOVQ m+24(FP), DI +popcntMaskSliceLoop: +MOVQ (DI), DX +NOTQ DX +ANDQ (SI), DX +POPCNTQ_DX_DX +ADDQ DX, AX +ADDQ $8, SI +ADDQ $8, DI +LOOP popcntMaskSliceLoop +popcntMaskSliceEnd: +MOVQ AX, ret+48(FP) +RET + +TEXT ·popcntAndSliceAsm(SB),4,$0-56 +XORQ AX, AX +MOVQ s+0(FP), SI +MOVQ s_len+8(FP), CX +TESTQ CX, CX +JZ popcntAndSliceEnd +MOVQ m+24(FP), DI +popcntAndSliceLoop: +MOVQ (DI), DX +ANDQ (SI), DX +POPCNTQ_DX_DX +ADDQ DX, AX +ADDQ $8, SI +ADDQ $8, DI +LOOP popcntAndSliceLoop +popcntAndSliceEnd: +MOVQ AX, ret+48(FP) +RET + +TEXT ·popcntOrSliceAsm(SB),4,$0-56 +XORQ AX, AX +MOVQ s+0(FP), SI +MOVQ s_len+8(FP), CX +TESTQ CX, CX +JZ popcntOrSliceEnd +MOVQ m+24(FP), DI +popcntOrSliceLoop: +MOVQ (DI), DX +ORQ (SI), DX +POPCNTQ_DX_DX +ADDQ DX, AX +ADDQ $8, SI +ADDQ $8, DI +LOOP popcntOrSliceLoop +popcntOrSliceEnd: +MOVQ AX, ret+48(FP) +RET + +TEXT ·popcntXorSliceAsm(SB),4,$0-56 +XORQ AX, AX +MOVQ s+0(FP), SI +MOVQ s_len+8(FP), CX +TESTQ CX, CX +JZ popcntXorSliceEnd +MOVQ m+24(FP), DI +popcntXorSliceLoop: +MOVQ (DI), DX +XORQ (SI), DX +POPCNTQ_DX_DX +ADDQ DX, AX +ADDQ $8, SI +ADDQ $8, DI +LOOP popcntXorSliceLoop +popcntXorSliceEnd: +MOVQ AX, ret+48(FP) +RET diff --git a/vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go b/vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go new file mode 100644 index 00000000..9e0ad464 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/popcnt_generic.go @@ -0,0 +1,25 @@ +//go:build !go1.9 && (!amd64 || appengine) +// +build !go1.9 +// +build !amd64 appengine + +package bitset + +func popcntSlice(s []uint64) uint64 { + return popcntSliceGo(s) +} + +func popcntMaskSlice(s, m []uint64) uint64 { + return popcntMaskSliceGo(s, m) +} + +func popcntAndSlice(s, m []uint64) uint64 { + return popcntAndSliceGo(s, m) +} + +func popcntOrSlice(s, m []uint64) uint64 { + return popcntOrSliceGo(s, m) +} + +func popcntXorSlice(s, m []uint64) uint64 { + return popcntXorSliceGo(s, m) +} diff --git a/vendor/github.com/bits-and-blooms/bitset/select.go b/vendor/github.com/bits-and-blooms/bitset/select.go new file mode 100644 index 00000000..f15e74a2 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/select.go @@ -0,0 +1,45 @@ +package bitset + +func select64(w uint64, j uint) uint { + seen := 0 + // Divide 64bit + part := w & 0xFFFFFFFF + n := uint(popcount(part)) + if n <= j { + part = w >> 32 + seen += 32 + j -= n + } + ww := part + + // Divide 32bit + part = ww & 0xFFFF + + n = uint(popcount(part)) + if n <= j { + part = ww >> 16 + seen += 16 + j -= n + } + ww = part + + // Divide 16bit + part = ww & 0xFF + n = uint(popcount(part)) + if n <= j { + part = ww >> 8 + seen += 8 + j -= n + } + ww = part + + // Lookup in final byte + counter := 0 + for ; counter < 8; counter++ { + j -= uint((ww >> counter) & 1) + if j+1 == 0 { + break + } + } + return uint(seen + counter) +} diff --git a/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go b/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go new file mode 100644 index 00000000..12336e76 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_18.go @@ -0,0 +1,15 @@ +//go:build !go1.9 +// +build !go1.9 + +package bitset + +var deBruijn = [...]byte{ + 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, + 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, + 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, + 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, +} + +func trailingZeroes64(v uint64) uint { + return uint(deBruijn[((v&-v)*0x03f79d71b4ca8b09)>>58]) +} diff --git a/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go b/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go new file mode 100644 index 00000000..cfb0a840 --- /dev/null +++ b/vendor/github.com/bits-and-blooms/bitset/trailing_zeros_19.go @@ -0,0 +1,10 @@ +//go:build go1.9 +// +build go1.9 + +package bitset + +import "math/bits" + +func trailingZeroes64(v uint64) uint { + return uint(bits.TrailingZeros64(v)) +} diff --git a/vendor/github.com/coreos/go-iptables/LICENSE b/vendor/github.com/coreos/go-iptables/LICENSE new file mode 100644 index 00000000..37ec93a1 --- /dev/null +++ b/vendor/github.com/coreos/go-iptables/LICENSE @@ -0,0 +1,191 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and +distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct or +indirect, to cause the direction or management of such entity, whether by +contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the +outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising +permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + +"Object" form shall mean any form resulting from mechanical transformation or +translation of a Source form, including but not limited to compiled object code, +generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made +available under the License, as indicated by a copyright notice that is included +in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that +is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative Works +shall not include works that remain separable from, or merely link (or bind by +name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative Works +thereof, that is intentionally submitted to Licensor for inclusion in the Work +by the copyright owner or by an individual or Legal Entity authorized to submit +on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication sent +to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor for +the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently +incorporated within the Work. + +2. Grant of Copyright License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable copyright license to reproduce, prepare Derivative Works of, +publicly display, publicly perform, sublicense, and distribute the Work and such +Derivative Works in Source or Object form. + +3. Grant of Patent License. + +Subject to the terms and conditions of this License, each Contributor hereby +grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, +irrevocable (except as stated in this section) patent license to make, have +made, use, offer to sell, sell, import, and otherwise transfer the Work, where +such license applies only to those patent claims licensable by such Contributor +that are necessarily infringed by their Contribution(s) alone or by combination +of their Contribution(s) with the Work to which such Contribution(s) was +submitted. If You institute patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Work or a +Contribution incorporated within the Work constitutes direct or contributory +patent infringement, then any patent licenses granted to You under this License +for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. + +You may reproduce and distribute copies of the Work or Derivative Works thereof +in any medium, with or without modifications, and in Source or Object form, +provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of +this License; and +You must cause any modified files to carry prominent notices stating that You +changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source form +of the Work, excluding those notices that do not pertain to any part of the +Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any +Derivative Works that You distribute must include a readable copy of the +attribution notices contained within such NOTICE file, excluding those notices +that do not pertain to any part of the Derivative Works, in at least one of the +following places: within a NOTICE text file distributed as part of the +Derivative Works; within the Source form or documentation, if provided along +with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents of +the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works that +You distribute, alongside or as an addendum to the NOTICE text from the Work, +provided that such additional attribution notices cannot be construed as +modifying the License. +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, or +distribution of Your modifications, or for any such Derivative Works as a whole, +provided Your use, reproduction, and distribution of the Work otherwise complies +with the conditions stated in this License. + +5. Submission of Contributions. + +Unless You explicitly state otherwise, any Contribution intentionally submitted +for inclusion in the Work by You to the Licensor shall be under the terms and +conditions of this License, without any additional terms or conditions. +Notwithstanding the above, nothing herein shall supersede or modify the terms of +any separate license agreement you may have executed with Licensor regarding +such Contributions. + +6. Trademarks. + +This License does not grant permission to use the trade names, trademarks, +service marks, or product names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. + +Unless required by applicable law or agreed to in writing, Licensor provides the +Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, +including, without limitation, any warranties or conditions of TITLE, +NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are +solely responsible for determining the appropriateness of using or +redistributing the Work and assume any risks associated with Your exercise of +permissions under this License. + +8. Limitation of Liability. + +In no event and under no legal theory, whether in tort (including negligence), +contract, or otherwise, unless required by applicable law (such as deliberate +and grossly negligent acts) or agreed to in writing, shall any Contributor be +liable to You for damages, including any direct, indirect, special, incidental, +or consequential damages of any character arising as a result of this License or +out of the use or inability to use the Work (including but not limited to +damages for loss of goodwill, work stoppage, computer failure or malfunction, or +any and all other commercial damages or losses), even if such Contributor has +been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. + +While redistributing the Work or Derivative Works thereof, You may choose to +offer, and charge a fee for, acceptance of support, warranty, indemnity, or +other liability obligations and/or rights consistent with this License. However, +in accepting such obligations, You may act only on Your own behalf and on Your +sole responsibility, not on behalf of any other Contributor, and only if You +agree to indemnify, defend, and hold each Contributor harmless for any liability +incurred by, or claims asserted against, such Contributor by reason of your +accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own +identifying information. (Don't include the brackets!) The text should be +enclosed in the appropriate comment syntax for the file format. We also +recommend that a file or class name and description of purpose be included on +the same "printed page" as the copyright notice for easier identification within +third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/coreos/go-iptables/NOTICE b/vendor/github.com/coreos/go-iptables/NOTICE new file mode 100644 index 00000000..23a0ada2 --- /dev/null +++ b/vendor/github.com/coreos/go-iptables/NOTICE @@ -0,0 +1,5 @@ +CoreOS Project +Copyright 2018 CoreOS, Inc + +This product includes software developed at CoreOS, Inc. +(http://www.coreos.com/). diff --git a/vendor/github.com/coreos/go-iptables/iptables/iptables.go b/vendor/github.com/coreos/go-iptables/iptables/iptables.go new file mode 100644 index 00000000..6c5bbd70 --- /dev/null +++ b/vendor/github.com/coreos/go-iptables/iptables/iptables.go @@ -0,0 +1,745 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package iptables + +import ( + "bytes" + "fmt" + "io" + "net" + "os/exec" + "regexp" + "strconv" + "strings" + "syscall" +) + +// Adds the output of stderr to exec.ExitError +type Error struct { + exec.ExitError + cmd exec.Cmd + msg string + exitStatus *int //for overriding +} + +func (e *Error) ExitStatus() int { + if e.exitStatus != nil { + return *e.exitStatus + } + return e.Sys().(syscall.WaitStatus).ExitStatus() +} + +func (e *Error) Error() string { + return fmt.Sprintf("running %v: exit status %v: %v", e.cmd.Args, e.ExitStatus(), e.msg) +} + +var isNotExistPatterns = []string{ + "Bad rule (does a matching rule exist in that chain?).\n", + "No chain/target/match by that name.\n", + "No such file or directory", + "does not exist", +} + +// IsNotExist returns true if the error is due to the chain or rule not existing +func (e *Error) IsNotExist() bool { + for _, str := range isNotExistPatterns { + if strings.Contains(e.msg, str) { + return true + } + } + return false +} + +// Protocol to differentiate between IPv4 and IPv6 +type Protocol byte + +const ( + ProtocolIPv4 Protocol = iota + ProtocolIPv6 +) + +type IPTables struct { + path string + proto Protocol + hasCheck bool + hasWait bool + waitSupportSecond bool + hasRandomFully bool + v1 int + v2 int + v3 int + mode string // the underlying iptables operating mode, e.g. nf_tables + timeout int // time to wait for the iptables lock, default waits forever +} + +// Stat represents a structured statistic entry. +type Stat struct { + Packets uint64 `json:"pkts"` + Bytes uint64 `json:"bytes"` + Target string `json:"target"` + Protocol string `json:"prot"` + Opt string `json:"opt"` + Input string `json:"in"` + Output string `json:"out"` + Source *net.IPNet `json:"source"` + Destination *net.IPNet `json:"destination"` + Options string `json:"options"` +} + +type option func(*IPTables) + +func IPFamily(proto Protocol) option { + return func(ipt *IPTables) { + ipt.proto = proto + } +} + +func Timeout(timeout int) option { + return func(ipt *IPTables) { + ipt.timeout = timeout + } +} + +func Path(path string) option { + return func(ipt *IPTables) { + ipt.path = path + } +} + +// New creates a new IPTables configured with the options passed as parameters. +// Supported parameters are: +// +// IPFamily(Protocol) +// Timeout(int) +// Path(string) +// +// For backwards compatibility, by default New uses IPv4 and timeout 0. +// i.e. you can create an IPv6 IPTables using a timeout of 5 seconds passing +// the IPFamily and Timeout options as follow: +// +// ip6t := New(IPFamily(ProtocolIPv6), Timeout(5)) +func New(opts ...option) (*IPTables, error) { + + ipt := &IPTables{ + proto: ProtocolIPv4, + timeout: 0, + path: "", + } + + for _, opt := range opts { + opt(ipt) + } + + // if path wasn't preset through New(Path()), autodiscover it + cmd := "" + if ipt.path == "" { + cmd = getIptablesCommand(ipt.proto) + } else { + cmd = ipt.path + } + path, err := exec.LookPath(cmd) + if err != nil { + return nil, err + } + ipt.path = path + + vstring, err := getIptablesVersionString(path) + if err != nil { + return nil, fmt.Errorf("could not get iptables version: %v", err) + } + v1, v2, v3, mode, err := extractIptablesVersion(vstring) + if err != nil { + return nil, fmt.Errorf("failed to extract iptables version from [%s]: %v", vstring, err) + } + ipt.v1 = v1 + ipt.v2 = v2 + ipt.v3 = v3 + ipt.mode = mode + + checkPresent, waitPresent, waitSupportSecond, randomFullyPresent := getIptablesCommandSupport(v1, v2, v3) + ipt.hasCheck = checkPresent + ipt.hasWait = waitPresent + ipt.waitSupportSecond = waitSupportSecond + ipt.hasRandomFully = randomFullyPresent + + return ipt, nil +} + +// New creates a new IPTables for the given proto. +// The proto will determine which command is used, either "iptables" or "ip6tables". +func NewWithProtocol(proto Protocol) (*IPTables, error) { + return New(IPFamily(proto), Timeout(0)) +} + +// Proto returns the protocol used by this IPTables. +func (ipt *IPTables) Proto() Protocol { + return ipt.proto +} + +// Exists checks if given rulespec in specified table/chain exists +func (ipt *IPTables) Exists(table, chain string, rulespec ...string) (bool, error) { + if !ipt.hasCheck { + return ipt.existsForOldIptables(table, chain, rulespec) + + } + cmd := append([]string{"-t", table, "-C", chain}, rulespec...) + err := ipt.run(cmd...) + eerr, eok := err.(*Error) + switch { + case err == nil: + return true, nil + case eok && eerr.ExitStatus() == 1: + return false, nil + default: + return false, err + } +} + +// Insert inserts rulespec to specified table/chain (in specified pos) +func (ipt *IPTables) Insert(table, chain string, pos int, rulespec ...string) error { + cmd := append([]string{"-t", table, "-I", chain, strconv.Itoa(pos)}, rulespec...) + return ipt.run(cmd...) +} + +// Replace replaces rulespec to specified table/chain (in specified pos) +func (ipt *IPTables) Replace(table, chain string, pos int, rulespec ...string) error { + cmd := append([]string{"-t", table, "-R", chain, strconv.Itoa(pos)}, rulespec...) + return ipt.run(cmd...) +} + +// InsertUnique acts like Insert except that it won't insert a duplicate (no matter the position in the chain) +func (ipt *IPTables) InsertUnique(table, chain string, pos int, rulespec ...string) error { + exists, err := ipt.Exists(table, chain, rulespec...) + if err != nil { + return err + } + + if !exists { + return ipt.Insert(table, chain, pos, rulespec...) + } + + return nil +} + +// Append appends rulespec to specified table/chain +func (ipt *IPTables) Append(table, chain string, rulespec ...string) error { + cmd := append([]string{"-t", table, "-A", chain}, rulespec...) + return ipt.run(cmd...) +} + +// AppendUnique acts like Append except that it won't add a duplicate +func (ipt *IPTables) AppendUnique(table, chain string, rulespec ...string) error { + exists, err := ipt.Exists(table, chain, rulespec...) + if err != nil { + return err + } + + if !exists { + return ipt.Append(table, chain, rulespec...) + } + + return nil +} + +// Delete removes rulespec in specified table/chain +func (ipt *IPTables) Delete(table, chain string, rulespec ...string) error { + cmd := append([]string{"-t", table, "-D", chain}, rulespec...) + return ipt.run(cmd...) +} + +func (ipt *IPTables) DeleteIfExists(table, chain string, rulespec ...string) error { + exists, err := ipt.Exists(table, chain, rulespec...) + if err == nil && exists { + err = ipt.Delete(table, chain, rulespec...) + } + return err +} + +// List rules in specified table/chain +func (ipt *IPTables) ListById(table, chain string, id int) (string, error) { + args := []string{"-t", table, "-S", chain, strconv.Itoa(id)} + rule, err := ipt.executeList(args) + if err != nil { + return "", err + } + return rule[0], nil +} + +// List rules in specified table/chain +func (ipt *IPTables) List(table, chain string) ([]string, error) { + args := []string{"-t", table, "-S", chain} + return ipt.executeList(args) +} + +// List rules (with counters) in specified table/chain +func (ipt *IPTables) ListWithCounters(table, chain string) ([]string, error) { + args := []string{"-t", table, "-v", "-S", chain} + return ipt.executeList(args) +} + +// ListChains returns a slice containing the name of each chain in the specified table. +func (ipt *IPTables) ListChains(table string) ([]string, error) { + args := []string{"-t", table, "-S"} + + result, err := ipt.executeList(args) + if err != nil { + return nil, err + } + + // Iterate over rules to find all default (-P) and user-specified (-N) chains. + // Chains definition always come before rules. + // Format is the following: + // -P OUTPUT ACCEPT + // -N Custom + var chains []string + for _, val := range result { + if strings.HasPrefix(val, "-P") || strings.HasPrefix(val, "-N") { + chains = append(chains, strings.Fields(val)[1]) + } else { + break + } + } + return chains, nil +} + +// '-S' is fine with non existing rule index as long as the chain exists +// therefore pass index 1 to reduce overhead for large chains +func (ipt *IPTables) ChainExists(table, chain string) (bool, error) { + err := ipt.run("-t", table, "-S", chain, "1") + eerr, eok := err.(*Error) + switch { + case err == nil: + return true, nil + case eok && eerr.ExitStatus() == 1: + return false, nil + default: + return false, err + } +} + +// Stats lists rules including the byte and packet counts +func (ipt *IPTables) Stats(table, chain string) ([][]string, error) { + args := []string{"-t", table, "-L", chain, "-n", "-v", "-x"} + lines, err := ipt.executeList(args) + if err != nil { + return nil, err + } + + appendSubnet := func(addr string) string { + if strings.IndexByte(addr, byte('/')) < 0 { + if strings.IndexByte(addr, '.') < 0 { + return addr + "/128" + } + return addr + "/32" + } + return addr + } + + ipv6 := ipt.proto == ProtocolIPv6 + + // Skip the warning if exist + if strings.HasPrefix(lines[0], "#") { + lines = lines[1:] + } + + rows := [][]string{} + for i, line := range lines { + // Skip over chain name and field header + if i < 2 { + continue + } + + // Fields: + // 0=pkts 1=bytes 2=target 3=prot 4=opt 5=in 6=out 7=source 8=destination 9=options + line = strings.TrimSpace(line) + fields := strings.Fields(line) + + // The ip6tables verbose output cannot be naively split due to the default "opt" + // field containing 2 single spaces. + if ipv6 { + // Check if field 6 is "opt" or "source" address + dest := fields[6] + ip, _, _ := net.ParseCIDR(dest) + if ip == nil { + ip = net.ParseIP(dest) + } + + // If we detected a CIDR or IP, the "opt" field is empty.. insert it. + if ip != nil { + f := []string{} + f = append(f, fields[:4]...) + f = append(f, " ") // Empty "opt" field for ip6tables + f = append(f, fields[4:]...) + fields = f + } + } + + // Adjust "source" and "destination" to include netmask, to match regular + // List output + fields[7] = appendSubnet(fields[7]) + fields[8] = appendSubnet(fields[8]) + + // Combine "options" fields 9... into a single space-delimited field. + options := fields[9:] + fields = fields[:9] + fields = append(fields, strings.Join(options, " ")) + rows = append(rows, fields) + } + return rows, nil +} + +// ParseStat parses a single statistic row into a Stat struct. The input should +// be a string slice that is returned from calling the Stat method. +func (ipt *IPTables) ParseStat(stat []string) (parsed Stat, err error) { + // For forward-compatibility, expect at least 10 fields in the stat + if len(stat) < 10 { + return parsed, fmt.Errorf("stat contained fewer fields than expected") + } + + // Convert the fields that are not plain strings + parsed.Packets, err = strconv.ParseUint(stat[0], 0, 64) + if err != nil { + return parsed, fmt.Errorf(err.Error(), "could not parse packets") + } + parsed.Bytes, err = strconv.ParseUint(stat[1], 0, 64) + if err != nil { + return parsed, fmt.Errorf(err.Error(), "could not parse bytes") + } + _, parsed.Source, err = net.ParseCIDR(stat[7]) + if err != nil { + return parsed, fmt.Errorf(err.Error(), "could not parse source") + } + _, parsed.Destination, err = net.ParseCIDR(stat[8]) + if err != nil { + return parsed, fmt.Errorf(err.Error(), "could not parse destination") + } + + // Put the fields that are strings + parsed.Target = stat[2] + parsed.Protocol = stat[3] + parsed.Opt = stat[4] + parsed.Input = stat[5] + parsed.Output = stat[6] + parsed.Options = stat[9] + + return parsed, nil +} + +// StructuredStats returns statistics as structured data which may be further +// parsed and marshaled. +func (ipt *IPTables) StructuredStats(table, chain string) ([]Stat, error) { + rawStats, err := ipt.Stats(table, chain) + if err != nil { + return nil, err + } + + structStats := []Stat{} + for _, rawStat := range rawStats { + stat, err := ipt.ParseStat(rawStat) + if err != nil { + return nil, err + } + structStats = append(structStats, stat) + } + + return structStats, nil +} + +func (ipt *IPTables) executeList(args []string) ([]string, error) { + var stdout bytes.Buffer + if err := ipt.runWithOutput(args, &stdout); err != nil { + return nil, err + } + + rules := strings.Split(stdout.String(), "\n") + + // strip trailing newline + if len(rules) > 0 && rules[len(rules)-1] == "" { + rules = rules[:len(rules)-1] + } + + for i, rule := range rules { + rules[i] = filterRuleOutput(rule) + } + + return rules, nil +} + +// NewChain creates a new chain in the specified table. +// If the chain already exists, it will result in an error. +func (ipt *IPTables) NewChain(table, chain string) error { + return ipt.run("-t", table, "-N", chain) +} + +const existsErr = 1 + +// ClearChain flushed (deletes all rules) in the specified table/chain. +// If the chain does not exist, a new one will be created +func (ipt *IPTables) ClearChain(table, chain string) error { + err := ipt.NewChain(table, chain) + + eerr, eok := err.(*Error) + switch { + case err == nil: + return nil + case eok && eerr.ExitStatus() == existsErr: + // chain already exists. Flush (clear) it. + return ipt.run("-t", table, "-F", chain) + default: + return err + } +} + +// RenameChain renames the old chain to the new one. +func (ipt *IPTables) RenameChain(table, oldChain, newChain string) error { + return ipt.run("-t", table, "-E", oldChain, newChain) +} + +// DeleteChain deletes the chain in the specified table. +// The chain must be empty +func (ipt *IPTables) DeleteChain(table, chain string) error { + return ipt.run("-t", table, "-X", chain) +} + +func (ipt *IPTables) ClearAndDeleteChain(table, chain string) error { + exists, err := ipt.ChainExists(table, chain) + if err != nil || !exists { + return err + } + err = ipt.run("-t", table, "-F", chain) + if err == nil { + err = ipt.run("-t", table, "-X", chain) + } + return err +} + +func (ipt *IPTables) ClearAll() error { + return ipt.run("-F") +} + +func (ipt *IPTables) DeleteAll() error { + return ipt.run("-X") +} + +// ChangePolicy changes policy on chain to target +func (ipt *IPTables) ChangePolicy(table, chain, target string) error { + return ipt.run("-t", table, "-P", chain, target) +} + +// Check if the underlying iptables command supports the --random-fully flag +func (ipt *IPTables) HasRandomFully() bool { + return ipt.hasRandomFully +} + +// Return version components of the underlying iptables command +func (ipt *IPTables) GetIptablesVersion() (int, int, int) { + return ipt.v1, ipt.v2, ipt.v3 +} + +// run runs an iptables command with the given arguments, ignoring +// any stdout output +func (ipt *IPTables) run(args ...string) error { + return ipt.runWithOutput(args, nil) +} + +// runWithOutput runs an iptables command with the given arguments, +// writing any stdout output to the given writer +func (ipt *IPTables) runWithOutput(args []string, stdout io.Writer) error { + args = append([]string{ipt.path}, args...) + if ipt.hasWait { + args = append(args, "--wait") + if ipt.timeout != 0 && ipt.waitSupportSecond { + args = append(args, strconv.Itoa(ipt.timeout)) + } + } else { + fmu, err := newXtablesFileLock() + if err != nil { + return err + } + ul, err := fmu.tryLock() + if err != nil { + syscall.Close(fmu.fd) + return err + } + defer func() { + _ = ul.Unlock() + }() + } + + var stderr bytes.Buffer + cmd := exec.Cmd{ + Path: ipt.path, + Args: args, + Stdout: stdout, + Stderr: &stderr, + } + + if err := cmd.Run(); err != nil { + switch e := err.(type) { + case *exec.ExitError: + return &Error{*e, cmd, stderr.String(), nil} + default: + return err + } + } + + return nil +} + +// getIptablesCommand returns the correct command for the given protocol, either "iptables" or "ip6tables". +func getIptablesCommand(proto Protocol) string { + if proto == ProtocolIPv6 { + return "ip6tables" + } else { + return "iptables" + } +} + +// Checks if iptables has the "-C" and "--wait" flag +func getIptablesCommandSupport(v1 int, v2 int, v3 int) (bool, bool, bool, bool) { + return iptablesHasCheckCommand(v1, v2, v3), iptablesHasWaitCommand(v1, v2, v3), iptablesWaitSupportSecond(v1, v2, v3), iptablesHasRandomFully(v1, v2, v3) +} + +// getIptablesVersion returns the first three components of the iptables version +// and the operating mode (e.g. nf_tables or legacy) +// e.g. "iptables v1.3.66" would return (1, 3, 66, legacy, nil) +func extractIptablesVersion(str string) (int, int, int, string, error) { + versionMatcher := regexp.MustCompile(`v([0-9]+)\.([0-9]+)\.([0-9]+)(?:\s+\((\w+))?`) + result := versionMatcher.FindStringSubmatch(str) + if result == nil { + return 0, 0, 0, "", fmt.Errorf("no iptables version found in string: %s", str) + } + + v1, err := strconv.Atoi(result[1]) + if err != nil { + return 0, 0, 0, "", err + } + + v2, err := strconv.Atoi(result[2]) + if err != nil { + return 0, 0, 0, "", err + } + + v3, err := strconv.Atoi(result[3]) + if err != nil { + return 0, 0, 0, "", err + } + + mode := "legacy" + if result[4] != "" { + mode = result[4] + } + return v1, v2, v3, mode, nil +} + +// Runs "iptables --version" to get the version string +func getIptablesVersionString(path string) (string, error) { + cmd := exec.Command(path, "--version") + var out bytes.Buffer + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + return "", err + } + return out.String(), nil +} + +// Checks if an iptables version is after 1.4.11, when --check was added +func iptablesHasCheckCommand(v1 int, v2 int, v3 int) bool { + if v1 > 1 { + return true + } + if v1 == 1 && v2 > 4 { + return true + } + if v1 == 1 && v2 == 4 && v3 >= 11 { + return true + } + return false +} + +// Checks if an iptables version is after 1.4.20, when --wait was added +func iptablesHasWaitCommand(v1 int, v2 int, v3 int) bool { + if v1 > 1 { + return true + } + if v1 == 1 && v2 > 4 { + return true + } + if v1 == 1 && v2 == 4 && v3 >= 20 { + return true + } + return false +} + +// Checks if an iptablse version is after 1.6.0, when --wait support second +func iptablesWaitSupportSecond(v1 int, v2 int, v3 int) bool { + if v1 > 1 { + return true + } + if v1 == 1 && v2 >= 6 { + return true + } + return false +} + +// Checks if an iptables version is after 1.6.2, when --random-fully was added +func iptablesHasRandomFully(v1 int, v2 int, v3 int) bool { + if v1 > 1 { + return true + } + if v1 == 1 && v2 > 6 { + return true + } + if v1 == 1 && v2 == 6 && v3 >= 2 { + return true + } + return false +} + +// Checks if a rule specification exists for a table +func (ipt *IPTables) existsForOldIptables(table, chain string, rulespec []string) (bool, error) { + rs := strings.Join(append([]string{"-A", chain}, rulespec...), " ") + args := []string{"-t", table, "-S"} + var stdout bytes.Buffer + err := ipt.runWithOutput(args, &stdout) + if err != nil { + return false, err + } + return strings.Contains(stdout.String(), rs), nil +} + +// counterRegex is the regex used to detect nftables counter format +var counterRegex = regexp.MustCompile(`^\[([0-9]+):([0-9]+)\] `) + +// filterRuleOutput works around some inconsistencies in output. +// For example, when iptables is in legacy vs. nftables mode, it produces +// different results. +func filterRuleOutput(rule string) string { + out := rule + + // work around an output difference in nftables mode where counters + // are output in iptables-save format, rather than iptables -S format + // The string begins with "[0:0]" + // + // Fixes #49 + if groups := counterRegex.FindStringSubmatch(out); groups != nil { + // drop the brackets + out = out[len(groups[0]):] + out = fmt.Sprintf("%s -c %s %s", out, groups[1], groups[2]) + } + + return out +} diff --git a/vendor/github.com/coreos/go-iptables/iptables/lock.go b/vendor/github.com/coreos/go-iptables/iptables/lock.go new file mode 100644 index 00000000..a88e92b4 --- /dev/null +++ b/vendor/github.com/coreos/go-iptables/iptables/lock.go @@ -0,0 +1,84 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package iptables + +import ( + "os" + "sync" + "syscall" +) + +const ( + // In earlier versions of iptables, the xtables lock was implemented + // via a Unix socket, but now flock is used via this lockfile: + // http://git.netfilter.org/iptables/commit/?id=aa562a660d1555b13cffbac1e744033e91f82707 + // Note the LSB-conforming "/run" directory does not exist on old + // distributions, so assume "/var" is symlinked + xtablesLockFilePath = "/var/run/xtables.lock" + + defaultFilePerm = 0600 +) + +type Unlocker interface { + Unlock() error +} + +type nopUnlocker struct{} + +func (_ nopUnlocker) Unlock() error { return nil } + +type fileLock struct { + // mu is used to protect against concurrent invocations from within this process + mu sync.Mutex + fd int +} + +// tryLock takes an exclusive lock on the xtables lock file without blocking. +// This is best-effort only: if the exclusive lock would block (i.e. because +// another process already holds it), no error is returned. Otherwise, any +// error encountered during the locking operation is returned. +// The returned Unlocker should be used to release the lock when the caller is +// done invoking iptables commands. +func (l *fileLock) tryLock() (Unlocker, error) { + l.mu.Lock() + err := syscall.Flock(l.fd, syscall.LOCK_EX|syscall.LOCK_NB) + switch err { + case syscall.EWOULDBLOCK: + l.mu.Unlock() + return nopUnlocker{}, nil + case nil: + return l, nil + default: + l.mu.Unlock() + return nil, err + } +} + +// Unlock closes the underlying file, which implicitly unlocks it as well. It +// also unlocks the associated mutex. +func (l *fileLock) Unlock() error { + defer l.mu.Unlock() + return syscall.Close(l.fd) +} + +// newXtablesFileLock opens a new lock on the xtables lockfile without +// acquiring the lock +func newXtablesFileLock() (*fileLock, error) { + fd, err := syscall.Open(xtablesLockFilePath, os.O_CREATE, defaultFilePerm) + if err != nil { + return nil, err + } + return &fileLock{fd: fd}, nil +} diff --git a/vendor/github.com/dblohm7/wingoes/.gitignore b/vendor/github.com/dblohm7/wingoes/.gitignore new file mode 100644 index 00000000..d27e8563 --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/.gitignore @@ -0,0 +1,19 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Vim +.*.swo +.*.swp + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/dblohm7/wingoes/LICENSE b/vendor/github.com/dblohm7/wingoes/LICENSE new file mode 100644 index 00000000..22e47c7e --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2022, Tailscale Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder 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 HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/dblohm7/wingoes/README.md b/vendor/github.com/dblohm7/wingoes/README.md new file mode 100644 index 00000000..794e35d9 --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/README.md @@ -0,0 +1,2 @@ +# wingoes, an opinionated library for writing Win32 programs in Go + diff --git a/vendor/github.com/dblohm7/wingoes/error.go b/vendor/github.com/dblohm7/wingoes/error.go new file mode 100644 index 00000000..baeacada --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/error.go @@ -0,0 +1,329 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package wingoes + +import ( + "fmt" + + "golang.org/x/sys/windows" +) + +// Error represents various error codes that may be encountered when coding +// against Windows APIs, including HRESULTs, windows.NTStatus, and windows.Errno. +type Error HRESULT + +// Errors are HRESULTs under the hood because the HRESULT encoding allows for +// all the other common types of Windows errors to be encoded within them. + +const ( + hrS_OK = HRESULT(0) + hrE_ABORT = HRESULT(-((0x80004004 ^ 0xFFFFFFFF) + 1)) + hrE_FAIL = HRESULT(-((0x80004005 ^ 0xFFFFFFFF) + 1)) + hrE_NOINTERFACE = HRESULT(-((0x80004002 ^ 0xFFFFFFFF) + 1)) + hrE_NOTIMPL = HRESULT(-((0x80004001 ^ 0xFFFFFFFF) + 1)) + hrE_POINTER = HRESULT(-((0x80004003 ^ 0xFFFFFFFF) + 1)) + hrE_UNEXPECTED = HRESULT(-((0x8000FFFF ^ 0xFFFFFFFF) + 1)) + hrTYPE_E_WRONGTYPEKIND = HRESULT(-((0x8002802A ^ 0xFFFFFFFF) + 1)) +) + +// S_FALSE is a peculiar HRESULT value which means that the call executed +// successfully, but returned false as its result. +const S_FALSE = HRESULT(1) + +var ( + // genericError encodes an Error whose message string is very generic. + genericError = Error(hresultFromFacilityAndCode(hrFail, facilityWin32, hrCode(windows.ERROR_UNIDENTIFIED_ERROR))) +) + +// Common HRESULT codes that don't use Win32 facilities, but have meanings that +// we can manually translate to Win32 error codes. +var commonHRESULTToErrno = map[HRESULT]windows.Errno{ + hrE_ABORT: windows.ERROR_REQUEST_ABORTED, + hrE_FAIL: windows.ERROR_UNIDENTIFIED_ERROR, + hrE_NOINTERFACE: windows.ERROR_NOINTERFACE, + hrE_NOTIMPL: windows.ERROR_CALL_NOT_IMPLEMENTED, + hrE_UNEXPECTED: windows.ERROR_INTERNAL_ERROR, +} + +type hrCode uint16 +type hrFacility uint16 +type failBit bool + +const ( + hrFlagBitsMask = 0xF8000000 + hrFacilityMax = 0x00001FFF + hrFacilityMask = hrFacilityMax << 16 + hrCodeMax = 0x0000FFFF + hrCodeMask = hrCodeMax + hrFailBit = 0x80000000 + hrCustomerBit = 0x20000000 // Also defined as syscall.APPLICATION_ERROR + hrFacilityNTBit = 0x10000000 +) + +const ( + facilityWin32 = hrFacility(7) +) + +// Succeeded returns true when hr is successful, but its actual error code +// may include additional status information. +func (hr HRESULT) Succeeded() bool { + return hr >= 0 +} + +// Failed returns true when hr contains a failure code. +func (hr HRESULT) Failed() bool { + return hr < 0 +} + +func (hr HRESULT) String() string { + return fmt.Sprintf("0x%08X", uint32(hr)) +} + +func (hr HRESULT) isNT() bool { + return (hr & (hrCustomerBit | hrFacilityNTBit)) == hrFacilityNTBit +} + +func (hr HRESULT) isCustomer() bool { + return (hr & hrCustomerBit) != 0 +} + +// isNormal returns true when the customer and NT bits are cleared, ie hr's +// encoding contains valid facility and code fields. +func (hr HRESULT) isNormal() bool { + return (hr & (hrCustomerBit | hrFacilityNTBit)) == 0 +} + +// facility returns the facility bits of hr. Only valid when isNormal is true. +func (hr HRESULT) facility() hrFacility { + return hrFacility((uint32(hr) >> 16) & hrFacilityMax) +} + +// facility returns the code bits of hr. Only valid when isNormal is true. +func (hr HRESULT) code() hrCode { + return hrCode(uint32(hr) & hrCodeMask) +} + +const ( + hrFail = failBit(true) + hrSuccess = failBit(false) +) + +func hresultFromFacilityAndCode(isFail failBit, f hrFacility, c hrCode) HRESULT { + var r uint32 + if isFail { + r |= hrFailBit + } + r |= (uint32(f) << 16) & hrFacilityMask + r |= uint32(c) & hrCodeMask + return HRESULT(r) +} + +// ErrorFromErrno creates an Error from e. +func ErrorFromErrno(e windows.Errno) Error { + if e == windows.ERROR_SUCCESS { + return Error(hrS_OK) + } + if ue := uint32(e); (ue & hrFlagBitsMask) == hrCustomerBit { + // syscall.APPLICATION_ERROR == hrCustomerBit, so the only other thing + // we need to do to transform this into an HRESULT is add the fail flag + return Error(HRESULT(ue | hrFailBit)) + } + if uint32(e) > hrCodeMax { + // Can't be encoded in HRESULT, return generic error instead + return genericError + } + return Error(hresultFromFacilityAndCode(hrFail, facilityWin32, hrCode(e))) +} + +// ErrorFromNTStatus creates an Error from s. +func ErrorFromNTStatus(s windows.NTStatus) Error { + if s == windows.STATUS_SUCCESS { + return Error(hrS_OK) + } + return Error(HRESULT(s) | hrFacilityNTBit) +} + +// ErrorFromHRESULT creates an Error from hr. +func ErrorFromHRESULT(hr HRESULT) Error { + return Error(hr) +} + +// NewError converts e into an Error if e's type is supported. It returns +// both the Error and a bool indicating whether the conversion was successful. +func NewError(e any) (Error, bool) { + switch v := e.(type) { + case Error: + return v, true + case windows.NTStatus: + return ErrorFromNTStatus(v), true + case windows.Errno: + return ErrorFromErrno(v), true + case HRESULT: + return ErrorFromHRESULT(v), true + default: + return ErrorFromHRESULT(hrTYPE_E_WRONGTYPEKIND), false + } +} + +// IsOK returns true when the Error is unconditionally successful. +func (e Error) IsOK() bool { + return HRESULT(e) == hrS_OK +} + +// Succeeded returns true when the Error is successful, but its error code +// may include additional status information. +func (e Error) Succeeded() bool { + return HRESULT(e).Succeeded() +} + +// Failed returns true when the Error contains a failure code. +func (e Error) Failed() bool { + return HRESULT(e).Failed() +} + +// AsHRESULT converts the Error to a HRESULT. +func (e Error) AsHRESULT() HRESULT { + return HRESULT(e) +} + +type errnoFailHandler func(hr HRESULT) windows.Errno + +func (e Error) toErrno(f errnoFailHandler) windows.Errno { + hr := HRESULT(e) + + if hr == hrS_OK { + return windows.ERROR_SUCCESS + } + + if hr.isCustomer() { + return windows.Errno(uint32(e) ^ hrFailBit) + } + + if hr.isNT() { + return e.AsNTStatus().Errno() + } + + if hr.facility() == facilityWin32 { + return windows.Errno(hr.code()) + } + + if errno, ok := commonHRESULTToErrno[hr]; ok { + return errno + } + + return f(hr) +} + +// AsError converts the Error to a windows.Errno, but panics if not possible. +func (e Error) AsErrno() windows.Errno { + handler := func(hr HRESULT) windows.Errno { + panic(fmt.Sprintf("wingoes.Error: Called AsErrno on a non-convertable HRESULT 0x%08X", uint32(hr))) + return windows.ERROR_UNIDENTIFIED_ERROR + } + + return e.toErrno(handler) +} + +type ntStatusFailHandler func(hr HRESULT) windows.NTStatus + +func (e Error) toNTStatus(f ntStatusFailHandler) windows.NTStatus { + hr := HRESULT(e) + + if hr == hrS_OK { + return windows.STATUS_SUCCESS + } + + if hr.isNT() { + return windows.NTStatus(hr ^ hrFacilityNTBit) + } + + return f(hr) +} + +// AsNTStatus converts the Error to a windows.NTStatus, but panics if not possible. +func (e Error) AsNTStatus() windows.NTStatus { + handler := func(hr HRESULT) windows.NTStatus { + panic(fmt.Sprintf("windows.Error: Called AsNTStatus on a non-NTSTATUS HRESULT 0x%08X", uint32(hr))) + return windows.STATUS_UNSUCCESSFUL + } + + return e.toNTStatus(handler) +} + +// TryAsErrno converts the Error to a windows.Errno, or returns defval if +// such a conversion is not possible. +func (e Error) TryAsErrno(defval windows.Errno) windows.Errno { + handler := func(hr HRESULT) windows.Errno { + return defval + } + + return e.toErrno(handler) +} + +// TryAsNTStatus converts the Error to a windows.NTStatus, or returns defval if +// such a conversion is not possible. +func (e Error) TryAsNTStatus(defval windows.NTStatus) windows.NTStatus { + handler := func(hr HRESULT) windows.NTStatus { + return defval + } + + return e.toNTStatus(handler) +} + +// IsAvailableAsHRESULT returns true if e may be converted to an HRESULT. +func (e Error) IsAvailableAsHRESULT() bool { + return true +} + +// IsAvailableAsErrno returns true if e may be converted to a windows.Errno. +func (e Error) IsAvailableAsErrno() bool { + hr := HRESULT(e) + if hr.isCustomer() || e.IsAvailableAsNTStatus() || (hr.facility() == facilityWin32) { + return true + } + _, convertable := commonHRESULTToErrno[hr] + return convertable +} + +// IsAvailableAsNTStatus returns true if e may be converted to a windows.NTStatus. +func (e Error) IsAvailableAsNTStatus() bool { + return HRESULT(e) == hrS_OK || HRESULT(e).isNT() +} + +// Error produces a human-readable message describing Error e. +func (e Error) Error() string { + if HRESULT(e).isCustomer() { + return windows.Errno(uint32(e) ^ hrFailBit).Error() + } + + buf := make([]uint16, 300) + const flags = windows.FORMAT_MESSAGE_FROM_SYSTEM | windows.FORMAT_MESSAGE_IGNORE_INSERTS + lenExclNul, err := windows.FormatMessage(flags, 0, uint32(e), 0, buf, nil) + if err != nil { + return fmt.Sprintf("wingoes.Error 0x%08X", uint32(e)) + } + for ; lenExclNul > 0 && (buf[lenExclNul-1] == '\n' || buf[lenExclNul-1] == '\r'); lenExclNul-- { + } + return windows.UTF16ToString(buf[:lenExclNul]) +} + +// Unwrap permits extraction of underlying windows.NTStatus or windows.Errno +// errors that are encoded within e. +func (e Error) Unwrap() error { + // Order is important! We need earlier checks to exclude certain things that + // would otherwise be (in this case) false positives in later checks! + switch { + case e.IsOK(): + return nil + case e.IsAvailableAsNTStatus(): + return e.AsNTStatus() + case e.IsAvailableAsErrno(): + return e.AsErrno() + default: + return nil + } +} diff --git a/vendor/github.com/dblohm7/wingoes/guid.go b/vendor/github.com/dblohm7/wingoes/guid.go new file mode 100644 index 00000000..da26361a --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/guid.go @@ -0,0 +1,15 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +package wingoes + +import ( + "fmt" +) + +func guidToString(guid GUID) string { + return fmt.Sprintf("{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + guid.Data1, guid.Data2, guid.Data3, + guid.Data4[0], guid.Data4[1], + guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]) +} diff --git a/vendor/github.com/dblohm7/wingoes/guid_notwindows.go b/vendor/github.com/dblohm7/wingoes/guid_notwindows.go new file mode 100644 index 00000000..28d9da33 --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/guid_notwindows.go @@ -0,0 +1,17 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !windows + +package wingoes + +type GUID struct { + Data1 uint32 + Data2 uint16 + Data3 uint16 + Data4 [8]byte +} + +func (guid GUID) String() string { + return guidToString(guid) +} diff --git a/vendor/github.com/dblohm7/wingoes/guid_windows.go b/vendor/github.com/dblohm7/wingoes/guid_windows.go new file mode 100644 index 00000000..b05cf4c7 --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/guid_windows.go @@ -0,0 +1,24 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package wingoes + +import ( + "fmt" + + "golang.org/x/sys/windows" +) + +type GUID = windows.GUID + +// MustGetGUID parses s, a string containing a GUID and returns a pointer to the +// parsed GUID. s must be specified in the format "{XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}". +// If there is an error parsing s, MustGetGUID panics. +func MustGetGUID(s string) *windows.GUID { + guid, err := windows.GUIDFromString(s) + if err != nil { + panic(fmt.Sprintf("wingoes.MustGetGUID(%q) error %v", s, err)) + } + return &guid +} diff --git a/vendor/github.com/dblohm7/wingoes/hresult.go b/vendor/github.com/dblohm7/wingoes/hresult.go new file mode 100644 index 00000000..84f9caa1 --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/hresult.go @@ -0,0 +1,12 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Note this file is explicitly available on non-Windows platforms, in order to +// aid `go generate` tooling on those platforms. It should not take a dependency +// on x/sys/windows. + +package wingoes + +// HRESULT is equivalent to the HRESULT type in the Win32 SDK for C/C++. +type HRESULT int32 diff --git a/vendor/github.com/dblohm7/wingoes/osversion.go b/vendor/github.com/dblohm7/wingoes/osversion.go new file mode 100644 index 00000000..7e90d2b2 --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/osversion.go @@ -0,0 +1,199 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package wingoes + +import ( + "fmt" + "sync" + + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" +) + +var ( + verOnce sync.Once + verInfo osVersionInfo // must access via getVersionInfo() +) + +// osVersionInfo is more compact than windows.OsVersionInfoEx, which contains +// extraneous information. +type osVersionInfo struct { + major uint32 + minor uint32 + build uint32 + servicePack uint16 + str string + isDC bool + isServer bool +} + +const ( + _VER_NT_WORKSTATION = 1 + _VER_NT_DOMAIN_CONTROLLER = 2 + _VER_NT_SERVER = 3 +) + +func getVersionInfo() *osVersionInfo { + verOnce.Do(func() { + osv := windows.RtlGetVersion() + verInfo = osVersionInfo{ + major: osv.MajorVersion, + minor: osv.MinorVersion, + build: osv.BuildNumber, + servicePack: osv.ServicePackMajor, + str: fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.BuildNumber), + isDC: osv.ProductType == _VER_NT_DOMAIN_CONTROLLER, + // Domain Controllers are also implicitly servers. + isServer: osv.ProductType == _VER_NT_DOMAIN_CONTROLLER || osv.ProductType == _VER_NT_SERVER, + } + // UBR is only available on Windows 10 and 11 (MajorVersion == 10). + if osv.MajorVersion == 10 { + if ubr, err := getUBR(); err == nil { + verInfo.str = fmt.Sprintf("%s.%d", verInfo.str, ubr) + } + } + }) + return &verInfo +} + +// getUBR returns the "update build revision," ie. the fourth component of the +// version string found on Windows 10 and Windows 11 systems. +func getUBR() (uint32, error) { + key, err := registry.OpenKey(registry.LOCAL_MACHINE, + `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE|registry.WOW64_64KEY) + if err != nil { + return 0, err + } + defer key.Close() + + val, valType, err := key.GetIntegerValue("UBR") + if err != nil { + return 0, err + } + if valType != registry.DWORD { + return 0, registry.ErrUnexpectedType + } + + return uint32(val), nil +} + +// GetOSVersionString returns the Windows version of the current machine in +// dotted-decimal form. The version string contains 3 components on Windows 7 +// and 8.x, and 4 components on Windows 10 and 11. +func GetOSVersionString() string { + return getVersionInfo().String() +} + +// IsWinServer returns true if and only if this computer's version of Windows is +// a server edition. +func IsWinServer() bool { + return getVersionInfo().isServer +} + +// IsWinDomainController returs true if this computer's version of Windows is +// configured to act as a domain controller. +func IsWinDomainController() bool { + return getVersionInfo().isDC +} + +// IsWin7SP1OrGreater returns true when running on Windows 7 SP1 or newer. +func IsWin7SP1OrGreater() bool { + if IsWin8OrGreater() { + return true + } + + vi := getVersionInfo() + return vi.major == 6 && vi.minor == 1 && vi.servicePack > 0 +} + +// IsWin8OrGreater returns true when running on Windows 8.0 or newer. +func IsWin8OrGreater() bool { + return getVersionInfo().isVersionOrGreater(6, 2, 0) +} + +// IsWin8Point1OrGreater returns true when running on Windows 8.1 or newer. +func IsWin8Point1OrGreater() bool { + return getVersionInfo().isVersionOrGreater(6, 3, 0) +} + +// IsWin10OrGreater returns true when running on any build of Windows 10 or newer. +func IsWin10OrGreater() bool { + return getVersionInfo().major >= 10 +} + +// Win10BuildConstant encodes build numbers for the various editions of Windows 10, +// for use with IsWin10BuildOrGreater. +type Win10BuildConstant uint32 + +const ( + Win10BuildRTM = Win10BuildConstant(10240) + Win10Build1511 = Win10BuildConstant(10586) + Win10Build1607 = Win10BuildConstant(14393) + Win10BuildAnniversary = Win10Build1607 + Win10Build1703 = Win10BuildConstant(15063) + Win10BuildCreators = Win10Build1703 + Win10Build1709 = Win10BuildConstant(16299) + Win10BuildFallCreators = Win10Build1709 + Win10Build1803 = Win10BuildConstant(17134) + Win10Build1809 = Win10BuildConstant(17763) + Win10Build1903 = Win10BuildConstant(18362) + Win10Build1909 = Win10BuildConstant(18363) + Win10Build2004 = Win10BuildConstant(19041) + Win10Build20H2 = Win10BuildConstant(19042) + Win10Build21H1 = Win10BuildConstant(19043) + Win10Build21H2 = Win10BuildConstant(19044) + Win10Build22H2 = Win10BuildConstant(19045) +) + +// IsWin10BuildOrGreater returns true when running on the specified Windows 10 +// build, or newer. +func IsWin10BuildOrGreater(build Win10BuildConstant) bool { + return getVersionInfo().isWin10BuildOrGreater(uint32(build)) +} + +// Win11BuildConstant encodes build numbers for the various editions of Windows 11, +// for use with IsWin11BuildOrGreater. +type Win11BuildConstant uint32 + +const ( + Win11BuildRTM = Win11BuildConstant(22000) + Win11Build22H2 = Win11BuildConstant(22621) + Win11Build23H2 = Win11BuildConstant(22631) +) + +// IsWin11OrGreater returns true when running on any release of Windows 11, +// or newer. +func IsWin11OrGreater() bool { + return IsWin11BuildOrGreater(Win11BuildRTM) +} + +// IsWin11BuildOrGreater returns true when running on the specified Windows 11 +// build, or newer. +func IsWin11BuildOrGreater(build Win11BuildConstant) bool { + // Under the hood, Windows 11 is just Windows 10 with a sufficiently advanced + // build number. + return getVersionInfo().isWin10BuildOrGreater(uint32(build)) +} + +func (osv *osVersionInfo) String() string { + return osv.str +} + +func (osv *osVersionInfo) isWin10BuildOrGreater(build uint32) bool { + return osv.isVersionOrGreater(10, 0, build) +} + +func (osv *osVersionInfo) isVersionOrGreater(major, minor, build uint32) bool { + return isVerGE(osv.major, major, osv.minor, minor, osv.build, build) +} + +func isVerGE(lmajor, rmajor, lminor, rminor, lbuild, rbuild uint32) bool { + return lmajor > rmajor || + lmajor == rmajor && + (lminor > rminor || + lminor == rminor && lbuild >= rbuild) +} diff --git a/vendor/github.com/dblohm7/wingoes/time.go b/vendor/github.com/dblohm7/wingoes/time.go new file mode 100644 index 00000000..e29a7f1b --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/time.go @@ -0,0 +1,29 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package wingoes + +import ( + "errors" + "time" + + "golang.org/x/sys/windows" +) + +var ( + // ErrDurationOutOfRange means that a time.Duration is too large to be able + // to be specified as a valid Win32 timeout value. + ErrDurationOutOfRange = errors.New("duration is out of timeout range") +) + +// DurationToTimeoutMilliseconds converts d into a timeout usable by Win32 APIs. +func DurationToTimeoutMilliseconds(d time.Duration) (uint32, error) { + millis := d.Milliseconds() + if millis >= windows.INFINITE { + return 0, ErrDurationOutOfRange + } + return uint32(millis), nil +} diff --git a/vendor/github.com/dblohm7/wingoes/util.go b/vendor/github.com/dblohm7/wingoes/util.go new file mode 100644 index 00000000..658f68aa --- /dev/null +++ b/vendor/github.com/dblohm7/wingoes/util.go @@ -0,0 +1,80 @@ +// Copyright (c) 2022 Tailscale Inc & AUTHORS. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package wingoes + +import ( + "unsafe" + + "golang.org/x/sys/windows" +) + +// UserSIDs contains pointers to the SIDs for a user and their primary group. +type UserSIDs struct { + User *windows.SID + PrimaryGroup *windows.SID +} + +// CurrentProcessUserSIDs returns a UserSIDs containing the SIDs of the user +// and primary group who own the current process. +func CurrentProcessUserSIDs() (*UserSIDs, error) { + token, err := windows.OpenCurrentProcessToken() + if err != nil { + return nil, err + } + defer token.Close() + + userInfo, err := token.GetTokenUser() + if err != nil { + return nil, err + } + + primaryGroup, err := token.GetTokenPrimaryGroup() + if err != nil { + return nil, err + } + + // We just want the SIDs, not the rest of the structs that were output. + userSid, err := userInfo.User.Sid.Copy() + if err != nil { + return nil, err + } + + primaryGroupSid, err := primaryGroup.PrimaryGroup.Copy() + if err != nil { + return nil, err + } + + return &UserSIDs{User: userSid, PrimaryGroup: primaryGroupSid}, nil +} + +// getTokenInfoVariableLen obtains variable-length token information. Use +// this function for information classes that output variable-length data. +func getTokenInfoVariableLen[T any](token windows.Token, infoClass uint32) (*T, error) { + var buf []byte + var desiredLen uint32 + + err := windows.GetTokenInformation(token, infoClass, nil, 0, &desiredLen) + + for err == windows.ERROR_INSUFFICIENT_BUFFER { + buf = make([]byte, desiredLen) + err = windows.GetTokenInformation(token, infoClass, unsafe.SliceData(buf), desiredLen, &desiredLen) + } + + if err != nil { + return nil, err + } + + return (*T)(unsafe.Pointer(unsafe.SliceData(buf))), nil +} + +// getTokenInfoFixedLen obtains known fixed-length token information. Use this +// function for information classes that output enumerations, BOOLs, integers etc. +func getTokenInfoFixedLen[T any](token windows.Token, infoClass uint32) (result T, _ error) { + var actualLen uint32 + err := windows.GetTokenInformation(token, infoClass, (*byte)(unsafe.Pointer(&result)), uint32(unsafe.Sizeof(result)), &actualLen) + return result, err +} diff --git a/vendor/github.com/docker/docker/AUTHORS b/vendor/github.com/docker/docker/AUTHORS index 48d04f9a..36315d42 100644 --- a/vendor/github.com/docker/docker/AUTHORS +++ b/vendor/github.com/docker/docker/AUTHORS @@ -669,6 +669,7 @@ Erik Hollensbe Erik Inge Bolsø Erik Kristensen Erik Sipsma +Erik Sjölund Erik St. Martin Erik Weathers Erno Hopearuoho @@ -731,6 +732,7 @@ Feroz Salam Ferran Rodenas Filipe Brandenburger Filipe Oliveira +Filipe Pina Flavio Castelli Flavio Crisciani Florian @@ -875,6 +877,8 @@ Hsing-Yu (David) Chen hsinko <21551195@zju.edu.cn> Hu Keping Hu Tao +Huajin Tong +huang-jl <1046678590@qq.com> HuanHuan Ye Huanzhong Zhang Huayi Zhang @@ -969,6 +973,7 @@ Jannick Fahlbusch Januar Wayong Jared Biel Jared Hocutt +Jaroslav Jindrak Jaroslaw Zabiello Jasmine Hegman Jason A. Donenfeld @@ -1012,6 +1017,7 @@ Jeffrey Bolle Jeffrey Morgan Jeffrey van Gogh Jenny Gebske +Jeongseok Kang Jeremy Chambers Jeremy Grosser Jeremy Huntwork @@ -1029,6 +1035,7 @@ Jezeniel Zapanta Jhon Honce Ji.Zhilong Jian Liao +Jian Zeng Jian Zhang Jiang Jinyang Jianyong Wu @@ -1967,6 +1974,7 @@ Sergey Evstifeev Sergii Kabashniuk Sergio Lopez Serhat Gülçiçek +Serhii Nakon SeungUkLee Sevki Hasirci Shane Canon @@ -2253,6 +2261,7 @@ VladimirAus Vladislav Kolesnikov Vlastimil Zeman Vojtech Vitek (V-Teq) +voloder <110066198+voloder@users.noreply.github.com> Walter Leibbrandt Walter Stanish Wang Chao diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml index 5677340d..43a780e9 100644 --- a/vendor/github.com/docker/docker/api/swagger.yaml +++ b/vendor/github.com/docker/docker/api/swagger.yaml @@ -2179,72 +2179,129 @@ definitions: type: "object" properties: Name: + description: | + Name of the network. type: "string" + example: "my_network" Id: + description: | + ID that uniquely identifies a network on a single machine. type: "string" + example: "7d86d31b1478e7cca9ebed7e73aa0fdeec46c5ca29497431d3007d2d9e15ed99" Created: + description: | + Date and time at which the network was created in + [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format with nano-seconds. type: "string" format: "dateTime" + example: "2016-10-19T04:33:30.360899459Z" Scope: + description: | + The level at which the network exists (e.g. `swarm` for cluster-wide + or `local` for machine level) type: "string" + example: "local" Driver: + description: | + The name of the driver used to create the network (e.g. `bridge`, + `overlay`). type: "string" + example: "overlay" EnableIPv6: + description: | + Whether the network was created with IPv6 enabled. type: "boolean" + example: false IPAM: $ref: "#/definitions/IPAM" Internal: + description: | + Whether the network is created to only allow internal networking + connectivity. type: "boolean" + default: false + example: false Attachable: + description: | + Wheter a global / swarm scope network is manually attachable by regular + containers from workers in swarm mode. type: "boolean" + default: false + example: false Ingress: + description: | + Whether the network is providing the routing-mesh for the swarm cluster. type: "boolean" + default: false + example: false + ConfigFrom: + $ref: "#/definitions/ConfigReference" + ConfigOnly: + description: | + Whether the network is a config-only network. Config-only networks are + placeholder networks for network configurations to be used by other + networks. Config-only networks cannot be used directly to run containers + or services. + type: "boolean" + default: false Containers: + description: | + Contains endpoints attached to the network. type: "object" additionalProperties: $ref: "#/definitions/NetworkContainer" + example: + 19a4d5d687db25203351ed79d478946f861258f018fe384f229f2efa4b23513c: + Name: "test" + EndpointID: "628cadb8bcb92de107b2a1e516cbffe463e321f548feb37697cce00ad694f21a" + MacAddress: "02:42:ac:13:00:02" + IPv4Address: "172.19.0.2/16" + IPv6Address: "" Options: + description: | + Network-specific options uses when creating the network. type: "object" additionalProperties: type: "string" + example: + com.docker.network.bridge.default_bridge: "true" + com.docker.network.bridge.enable_icc: "true" + com.docker.network.bridge.enable_ip_masquerade: "true" + com.docker.network.bridge.host_binding_ipv4: "0.0.0.0" + com.docker.network.bridge.name: "docker0" + com.docker.network.driver.mtu: "1500" Labels: + description: "User-defined key/value metadata." type: "object" additionalProperties: type: "string" - example: - Name: "net01" - Id: "7d86d31b1478e7cca9ebed7e73aa0fdeec46c5ca29497431d3007d2d9e15ed99" - Created: "2016-10-19T04:33:30.360899459Z" - Scope: "local" - Driver: "bridge" - EnableIPv6: false - IPAM: - Driver: "default" - Config: - - Subnet: "172.19.0.0/16" - Gateway: "172.19.0.1" - Options: - foo: "bar" - Internal: false - Attachable: false - Ingress: false - Containers: - 19a4d5d687db25203351ed79d478946f861258f018fe384f229f2efa4b23513c: - Name: "test" - EndpointID: "628cadb8bcb92de107b2a1e516cbffe463e321f548feb37697cce00ad694f21a" - MacAddress: "02:42:ac:13:00:02" - IPv4Address: "172.19.0.2/16" - IPv6Address: "" - Options: - com.docker.network.bridge.default_bridge: "true" - com.docker.network.bridge.enable_icc: "true" - com.docker.network.bridge.enable_ip_masquerade: "true" - com.docker.network.bridge.host_binding_ipv4: "0.0.0.0" - com.docker.network.bridge.name: "docker0" - com.docker.network.driver.mtu: "1500" - Labels: - com.example.some-label: "some-value" - com.example.some-other-label: "some-other-value" + example: + com.example.some-label: "some-value" + com.example.some-other-label: "some-other-value" + Peers: + description: | + List of peer nodes for an overlay network. This field is only present + for overlay networks, and omitted for other network types. + type: "array" + items: + $ref: "#/definitions/PeerInfo" + x-nullable: true + # TODO: Add Services (only present when "verbose" is set). + + ConfigReference: + description: | + The config-only network source to provide the configuration for + this network. + type: "object" + properties: + Network: + description: | + The name of the config-only network that provides the network's + configuration. The specified network must be an existing config-only + network. Only network names are allowed, not network IDs. + type: "string" + example: "config_only_network_01" + IPAM: type: "object" properties: @@ -2252,6 +2309,7 @@ definitions: description: "Name of the IPAM driver to use." type: "string" default: "default" + example: "default" Config: description: | List of IPAM configuration options, specified as a map: @@ -2267,16 +2325,21 @@ definitions: type: "object" additionalProperties: type: "string" + example: + foo: "bar" IPAMConfig: type: "object" properties: Subnet: type: "string" + example: "172.20.0.0/16" IPRange: type: "string" + example: "172.20.10.0/24" Gateway: type: "string" + example: "172.20.10.11" AuxiliaryAddresses: type: "object" additionalProperties: @@ -2287,14 +2350,35 @@ definitions: properties: Name: type: "string" + example: "container_1" EndpointID: type: "string" + example: "628cadb8bcb92de107b2a1e516cbffe463e321f548feb37697cce00ad694f21a" MacAddress: type: "string" + example: "02:42:ac:13:00:02" IPv4Address: type: "string" + example: "172.19.0.2/16" IPv6Address: type: "string" + example: "" + + PeerInfo: + description: | + PeerInfo represents one peer of an overlay network. + type: "object" + properties: + Name: + description: + ID of the peer-node in the Swarm cluster. + type: "string" + example: "6869d7c1732b" + IP: + description: + IP-address of the peer-node in the Swarm cluster. + type: "string" + example: "10.133.77.91" BuildInfo: type: "object" @@ -10104,14 +10188,22 @@ paths: Name: description: "The network's name." type: "string" + example: "my_network" CheckDuplicate: description: | Deprecated: CheckDuplicate is now always enabled. type: "boolean" + example: true Driver: description: "Name of the network driver plugin to use." type: "string" default: "bridge" + example: "bridge" + Scope: + description: | + The level at which the network exists (e.g. `swarm` for cluster-wide + or `local` for machine level). + type: "string" Internal: description: "Restrict external access to the network." type: "boolean" @@ -10120,55 +10212,55 @@ paths: Globally scoped network is manually attachable by regular containers from workers in swarm mode. type: "boolean" + example: true Ingress: description: | Ingress network is the network which provides the routing-mesh in swarm mode. type: "boolean" + example: false + ConfigOnly: + description: | + Creates a config-only network. Config-only networks are placeholder + networks for network configurations to be used by other networks. + Config-only networks cannot be used directly to run containers + or services. + type: "boolean" + default: false + example: false + ConfigFrom: + description: | + Specifies the source which will provide the configuration for + this network. The specified network must be an existing + config-only network; see ConfigOnly. + $ref: "#/definitions/ConfigReference" IPAM: description: "Optional custom IP scheme for the network." $ref: "#/definitions/IPAM" EnableIPv6: description: "Enable IPv6 on the network." type: "boolean" + example: true Options: description: "Network specific options to be used by the drivers." type: "object" additionalProperties: type: "string" + example: + com.docker.network.bridge.default_bridge: "true" + com.docker.network.bridge.enable_icc: "true" + com.docker.network.bridge.enable_ip_masquerade: "true" + com.docker.network.bridge.host_binding_ipv4: "0.0.0.0" + com.docker.network.bridge.name: "docker0" + com.docker.network.driver.mtu: "1500" Labels: description: "User-defined key/value metadata." type: "object" additionalProperties: type: "string" - example: - Name: "isolated_nw" - CheckDuplicate: false - Driver: "bridge" - EnableIPv6: true - IPAM: - Driver: "default" - Config: - - Subnet: "172.20.0.0/16" - IPRange: "172.20.10.0/24" - Gateway: "172.20.10.11" - - Subnet: "2001:db8:abcd::/64" - Gateway: "2001:db8:abcd::1011" - Options: - foo: "bar" - Internal: true - Attachable: false - Ingress: false - Options: - com.docker.network.bridge.default_bridge: "true" - com.docker.network.bridge.enable_icc: "true" - com.docker.network.bridge.enable_ip_masquerade: "true" - com.docker.network.bridge.host_binding_ipv4: "0.0.0.0" - com.docker.network.bridge.name: "docker0" - com.docker.network.driver.mtu: "1500" - Labels: - com.example.some-label: "some-value" - com.example.some-other-label: "some-other-value" + example: + com.example.some-label: "some-value" + com.example.some-other-label: "some-other-value" tags: ["Network"] /networks/{id}/connect: diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go index ca07162a..583b9cbe 100644 --- a/vendor/github.com/docker/docker/api/types/types.go +++ b/vendor/github.com/docker/docker/api/types/types.go @@ -457,24 +457,24 @@ type EndpointResource struct { type NetworkCreate struct { // Deprecated: CheckDuplicate is deprecated since API v1.44, but it defaults to true when sent by the client // package to older daemons. - CheckDuplicate bool `json:",omitempty"` - Driver string - Scope string - EnableIPv6 bool - IPAM *network.IPAM - Internal bool - Attachable bool - Ingress bool - ConfigOnly bool - ConfigFrom *network.ConfigReference - Options map[string]string - Labels map[string]string + CheckDuplicate bool `json:",omitempty"` + Driver string // Driver is the driver-name used to create the network (e.g. `bridge`, `overlay`) + Scope string // Scope describes the level at which the network exists (e.g. `swarm` for cluster-wide or `local` for machine level). + EnableIPv6 bool // EnableIPv6 represents whether to enable IPv6. + IPAM *network.IPAM // IPAM is the network's IP Address Management. + Internal bool // Internal represents if the network is used internal only. + Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode. + Ingress bool // Ingress indicates the network is providing the routing-mesh for the swarm cluster. + ConfigOnly bool // ConfigOnly creates a config-only network. Config-only networks are place-holder networks for network configurations to be used by other networks. ConfigOnly networks cannot be used directly to run containers or services. + ConfigFrom *network.ConfigReference // ConfigFrom specifies the source which will provide the configuration for this network. The specified network must be a config-only network; see [NetworkCreate.ConfigOnly]. + Options map[string]string // Options specifies the network-specific options to use for when creating the network. + Labels map[string]string // Labels holds metadata specific to the network being created. } // NetworkCreateRequest is the request message sent to the server for network create call. type NetworkCreateRequest struct { NetworkCreate - Name string + Name string // Name is the requested name of the network. } // NetworkCreateResponse is the response message sent by the server for network create call diff --git a/vendor/github.com/docker/docker/pkg/system/stat_illumos.go b/vendor/github.com/docker/docker/pkg/system/stat_illumos.go new file mode 100644 index 00000000..851374e5 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/stat_illumos.go @@ -0,0 +1,15 @@ +package system // import "github.com/docker/docker/pkg/system" + +import "syscall" + +// fromStatT converts a syscall.Stat_t type to a system.Stat_t type +func fromStatT(s *syscall.Stat_t) (*StatT, error) { + return &StatT{ + size: s.Size, + mode: uint32(s.Mode), + uid: s.Uid, + gid: s.Gid, + rdev: uint64(s.Rdev), + mtim: s.Mtim, + }, nil +} diff --git a/vendor/github.com/fxamacker/cbor/v2/.gitignore b/vendor/github.com/fxamacker/cbor/v2/.gitignore new file mode 100644 index 00000000..f1c181ec --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/.gitignore @@ -0,0 +1,12 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out diff --git a/vendor/github.com/fxamacker/cbor/v2/.golangci.yml b/vendor/github.com/fxamacker/cbor/v2/.golangci.yml new file mode 100644 index 00000000..e65c0533 --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/.golangci.yml @@ -0,0 +1,77 @@ +# Do not delete linter settings. Linters like gocritic can be enabled on the command line. + +linters-settings: + dupl: + threshold: 100 + funlen: + lines: 100 + statements: 50 + goconst: + min-len: 2 + min-occurrences: 3 + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + disabled-checks: + - dupImport # https://github.com/go-critic/go-critic/issues/845 + - ifElseChain + - octalLiteral + - paramTypeCombine + - whyNoLint + - wrapperFunc + gofmt: + simplify: false + goimports: + local-prefixes: github.com/fxamacker/cbor + golint: + min-confidence: 0 + govet: + check-shadowing: true + lll: + line-length: 140 + maligned: + suggest-new: true + misspell: + locale: US + +linters: + disable-all: true + enable: + - bidichk + - errcheck + - goconst + - gocyclo + - gofmt + - goimports + - gosec + - govet + - ineffassign + - misspell + - revive + - staticcheck + - typecheck + - unconvert + - unused + +issues: + # max-issues-per-linter default is 50. Set to 0 to disable limit. + max-issues-per-linter: 0 + # max-same-issues default is 3. Set to 0 to disable limit. + max-same-issues: 0 + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + - path: _test\.go + linters: + - goconst + - dupl + - gomnd + - lll + - path: doc\.go + linters: + - goimports + - gomnd + - lll diff --git a/vendor/github.com/fxamacker/cbor/v2/CODE_OF_CONDUCT.md b/vendor/github.com/fxamacker/cbor/v2/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..c794b2b0 --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/CODE_OF_CONDUCT.md @@ -0,0 +1,133 @@ + +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +faye.github@gmail.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.1, available at +[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at +[https://www.contributor-covenant.org/translations][translations]. + +[homepage]: https://www.contributor-covenant.org +[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html +[Mozilla CoC]: https://github.com/mozilla/diversity +[FAQ]: https://www.contributor-covenant.org/faq +[translations]: https://www.contributor-covenant.org/translations diff --git a/vendor/github.com/fxamacker/cbor/v2/CONTRIBUTING.md b/vendor/github.com/fxamacker/cbor/v2/CONTRIBUTING.md new file mode 100644 index 00000000..de0965e1 --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/CONTRIBUTING.md @@ -0,0 +1,41 @@ +# How to contribute + +You can contribute by using the library, opening issues, or opening pull requests. + +## Bug reports and security vulnerabilities + +Most issues are tracked publicly on [GitHub](https://github.com/fxamacker/cbor/issues). + +To report security vulnerabilities, please email faye.github@gmail.com and allow time for the problem to be resolved before disclosing it to the public. For more info, see [Security Policy](https://github.com/fxamacker/cbor#security-policy). + +Please do not send data that might contain personally identifiable information, even if you think you have permission. That type of support requires payment and a signed contract where I'm indemnified, held harmless, and defended by you for any data you send to me. + +## Pull requests + +Please [create an issue](https://github.com/fxamacker/cbor/issues/new/choose) before you begin work on a PR. The improvement may have already been considered, etc. + +Pull requests have signing requirements and must not be anonymous. Exceptions are usually made for docs and CI scripts. + +See the [Pull Request Template](https://github.com/fxamacker/cbor/blob/master/.github/pull_request_template.md) for details. + +Pull requests have a greater chance of being approved if: +- it does not reduce speed, increase memory use, reduce security, etc. for people not using the new option or feature. +- it has > 97% code coverage. + +## Describe your issue + +Clearly describe the issue: +* If it's a bug, please provide: **version of this library** and **Go** (`go version`), **unmodified error message**, and describe **how to reproduce it**. Also state **what you expected to happen** instead of the error. +* If you propose a change or addition, try to give an example how the improved code could look like or how to use it. +* If you found a compilation error, please confirm you're using a supported version of Go. If you are, then provide the output of `go version` first, followed by the complete error message. + +## Please don't + +Please don't send data containing personally identifiable information, even if you think you have permission. That type of support requires payment and a contract where I'm indemnified, held harmless, and defended for any data you send to me. + +Please don't send CBOR data larger than 1024 bytes by email. If you want to send crash-producing CBOR data > 1024 bytes by email, please get my permission before sending it to me. + +## Credits + +- This guide used nlohmann/json contribution guidelines for inspiration as suggested in issue #22. +- Special thanks to @lukseven for pointing out the contribution guidelines didn't mention signing requirements. diff --git a/vendor/github.com/fxamacker/cbor/v2/LICENSE b/vendor/github.com/fxamacker/cbor/v2/LICENSE new file mode 100644 index 00000000..eaa85049 --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019-present Faye Amacker + +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. \ No newline at end of file diff --git a/vendor/github.com/fxamacker/cbor/v2/README.md b/vendor/github.com/fxamacker/cbor/v2/README.md new file mode 100644 index 00000000..2bed2e6e --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/README.md @@ -0,0 +1,674 @@ +# CBOR Codec in Go + + + +[fxamacker/cbor](https://github.com/fxamacker/cbor) is a library for encoding and decoding [CBOR](https://www.rfc-editor.org/info/std94) and [CBOR Sequences](https://www.rfc-editor.org/rfc/rfc8742.html). + +CBOR is a [trusted alternative](https://www.rfc-editor.org/rfc/rfc8949.html#name-comparison-of-other-binary-) to JSON, MessagePack, Protocol Buffers, etc.  CBOR is an Internet Standard defined by [IETF STD 94 (RFC 8949)](https://www.rfc-editor.org/info/std94) and is designed to be relevant for decades. + +`fxamacker/cbor` is used in projects by Arm Ltd., Cisco, Dapper Labs, EdgeX Foundry, Fraunhofer‑AISEC, Let's Encrypt (ISRG), Linux Foundation, Microsoft, Mozilla, Oasis Protocol, Tailscale, Teleport, [and others](https://github.com/fxamacker/cbor#who-uses-fxamackercbor). + +See [Quick Start](#quick-start) and [Releases](https://github.com/fxamacker/cbor/releases/). 🆕 `UnmarshalFirst` and `DiagnoseFirst` can decode CBOR Sequences. + +## fxamacker/cbor + +[![](https://github.com/fxamacker/cbor/workflows/ci/badge.svg)](https://github.com/fxamacker/cbor/actions?query=workflow%3Aci) +[![](https://github.com/fxamacker/cbor/workflows/cover%20%E2%89%A596%25/badge.svg)](https://github.com/fxamacker/cbor/actions?query=workflow%3A%22cover+%E2%89%A596%25%22) +[![CodeQL](https://github.com/fxamacker/cbor/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/fxamacker/cbor/actions/workflows/codeql-analysis.yml) +[![](https://img.shields.io/badge/fuzzing-passing-44c010)](#fuzzing-and-code-coverage) +[![Go Report Card](https://goreportcard.com/badge/github.com/fxamacker/cbor)](https://goreportcard.com/report/github.com/fxamacker/cbor) +[![](https://img.shields.io/ossf-scorecard/github.com/fxamacker/cbor?label=openssf%20scorecard)](https://github.com/fxamacker/cbor#fuzzing-and-code-coverage) + +`fxamacker/cbor` is a CBOR codec in full conformance with [IETF STD 94 (RFC 8949)](https://www.rfc-editor.org/info/std94). It also supports CBOR Sequences ([RFC 8742](https://www.rfc-editor.org/rfc/rfc8742.html)) and Extended Diagnostic Notation ([Appendix G of RFC 8610](https://www.rfc-editor.org/rfc/rfc8610.html#appendix-G)). + +Features include full support for CBOR tags, [Core Deterministic Encoding](https://www.rfc-editor.org/rfc/rfc8949.html#name-core-deterministic-encoding), duplicate map key detection, etc. + +Design balances trade-offs between security, speed, concurrency, encoded data size, usability, etc. + +
Highlights

+ +__🚀  Speed__ + +Encoding and decoding is fast without using Go's `unsafe` package. Slower settings are opt-in. Default limits allow very fast and memory efficient rejection of malformed CBOR data. + +__🔒  Security__ + +Decoder has configurable limits that defend against malicious inputs. Duplicate map key detection is supported. By contrast, `encoding/gob` is [not designed to be hardened against adversarial inputs](https://pkg.go.dev/encoding/gob#hdr-Security). + +Codec passed multiple confidential security assessments in 2022. No vulnerabilities found in subset of codec in a [nonconfidential security assessment](https://github.com/veraison/go-cose/blob/v1.0.0-rc.1/reports/NCC_Microsoft-go-cose-Report_2022-05-26_v1.0.pdf) prepared by NCC Group for Microsoft Corporation. + +__🗜️  Data Size__ + +Struct tags (`toarray`, `keyasint`, `omitempty`) automatically reduce size of encoded structs. Encoding optionally shrinks float64→32→16 when values fit. + +__:jigsaw:  Usability__ + +API is mostly same as `encoding/json` plus interfaces that simplify concurrency for CBOR options. Encoding and decoding modes can be created at startup and reused by any goroutines. + +Presets include Core Deterministic Encoding, Preferred Serialization, CTAP2 Canonical CBOR, etc. + +__📆  Extensibility__ + +Features include CBOR [extension points](https://www.rfc-editor.org/rfc/rfc8949.html#section-7.1) (e.g. CBOR tags) and extensive settings. API has interfaces that allow users to create custom encoding and decoding without modifying this library. + +


+ +
+ +### Secure Decoding with Configurable Settings + +`fxamacker/cbor` has configurable limits, etc. that defend against malicious CBOR data. + +By contrast, `encoding/gob` is [not designed to be hardened against adversarial inputs](https://pkg.go.dev/encoding/gob#hdr-Security). + +
Example decoding with encoding/gob 💥 fatal error (out of memory)

+ +```Go +// Example of encoding/gob having "fatal error: runtime: out of memory" +// while decoding 181 bytes. +package main +import ( + "bytes" + "encoding/gob" + "encoding/hex" + "fmt" +) + +// Example data is from https://github.com/golang/go/issues/24446 +// (shortened to 181 bytes). +const data = "4dffb503010102303001ff30000109010130010800010130010800010130" + + "01ffb80001014a01ffb60001014b01ff860001013001ff860001013001ff" + + "860001013001ff860001013001ffb80000001eff850401010e3030303030" + + "30303030303030303001ff3000010c0104000016ffb70201010830303030" + + "3030303001ff3000010c000030ffb6040405fcff00303030303030303030" + + "303030303030303030303030303030303030303030303030303030303030" + + "30" + +type X struct { + J *X + K map[string]int +} + +func main() { + raw, _ := hex.DecodeString(data) + decoder := gob.NewDecoder(bytes.NewReader(raw)) + + var x X + decoder.Decode(&x) // fatal error: runtime: out of memory + fmt.Println("Decoding finished.") +} +``` + +


+ +
+ +`fxamacker/cbor` is fast at rejecting malformed CBOR data. E.g. attempts to +decode 10 bytes of malicious CBOR data to `[]byte` (with default settings): + +| Codec | Speed (ns/op) | Memory | Allocs | +| :---- | ------------: | -----: | -----: | +| fxamacker/cbor 2.5.0 | 44 ± 5% | 32 B/op | 2 allocs/op | +| ugorji/go 1.2.11 | 5353261 ± 4% | 67111321 B/op | 13 allocs/op | + +
Benchmark details

+ +Latest comparison used: +- Input: `[]byte{0x9B, 0x00, 0x00, 0x42, 0xFA, 0x42, 0xFA, 0x42, 0xFA, 0x42}` +- go1.19.10, linux/amd64, i5-13600K (disabled all e-cores, DDR4 @2933) +- go test -bench=. -benchmem -count=20 + +#### Prior comparisons + +| Codec | Speed (ns/op) | Memory | Allocs | +| :---- | ------------: | -----: | -----: | +| fxamacker/cbor 2.5.0-beta2 | 44.33 ± 2% | 32 B/op | 2 allocs/op | +| fxamacker/cbor 0.1.0 - 2.4.0 | ~44.68 ± 6% | 32 B/op | 2 allocs/op | +| ugorji/go 1.2.10 | 5524792.50 ± 3% | 67110491 B/op | 12 allocs/op | +| ugorji/go 1.1.0 - 1.2.6 | 💥 runtime: | out of memory: | cannot allocate | + +- Input: `[]byte{0x9B, 0x00, 0x00, 0x42, 0xFA, 0x42, 0xFA, 0x42, 0xFA, 0x42}` +- go1.19.6, linux/amd64, i5-13600K (DDR4) +- go test -bench=. -benchmem -count=20 + +


+ +
+ +### Smaller Encodings with Struct Tags + +Struct tags (`toarray`, `keyasint`, `omitempty`) reduce encoded size of structs. + +
Example encoding 3-level nested Go struct to 1 byte CBOR

+ +https://go.dev/play/p/YxwvfPdFQG2 + +```Go +// Example encoding nested struct (with omitempty tag) +// - encoding/json: 18 byte JSON +// - fxamacker/cbor: 1 byte CBOR +package main + +import ( + "encoding/hex" + "encoding/json" + "fmt" + + "github.com/fxamacker/cbor/v2" +) + +type GrandChild struct { + Quux int `json:",omitempty"` +} + +type Child struct { + Baz int `json:",omitempty"` + Qux GrandChild `json:",omitempty"` +} + +type Parent struct { + Foo Child `json:",omitempty"` + Bar int `json:",omitempty"` +} + +func cb() { + results, _ := cbor.Marshal(Parent{}) + fmt.Println("hex(CBOR): " + hex.EncodeToString(results)) + + text, _ := cbor.Diagnose(results) // Diagnostic Notation + fmt.Println("DN: " + text) +} + +func js() { + results, _ := json.Marshal(Parent{}) + fmt.Println("hex(JSON): " + hex.EncodeToString(results)) + + text := string(results) // JSON + fmt.Println("JSON: " + text) +} + +func main() { + cb() + fmt.Println("-------------") + js() +} +``` + +Output (DN is Diagnostic Notation): +``` +hex(CBOR): a0 +DN: {} +------------- +hex(JSON): 7b22466f6f223a7b22517578223a7b7d7d7d +JSON: {"Foo":{"Qux":{}}} +``` + +


+ +
+ +Example using different struct tags together: + +![alt text](https://github.com/fxamacker/images/raw/master/cbor/v2.3.0/cbor_struct_tags_api.svg?sanitize=1 "CBOR API and Go Struct Tags") + +API is mostly same as `encoding/json`, plus interfaces that simplify concurrency for CBOR options. + +## Quick Start + +__Install__: `go get github.com/fxamacker/cbor/v2` and `import "github.com/fxamacker/cbor/v2"`. + +### Key Points + +This library can encode and decode CBOR (RFC 8949) and CBOR Sequences (RFC 8742). + +- __CBOR data item__ is a single piece of CBOR data and its structure may contain zero, one, or more nested data items. +- __CBOR sequence__ is a concatenation of 0 or more encoded CBOR data items. + +Configurable limits and options can be used to balance trade-offs. + +- Encoding and decoding modes are created from options (settings). +- Modes can be created at startup and reused. +- Modes are safe for concurrent use. + +### Default Mode + +Package level functions only use this library's default settings. +They provide the "default mode" of encoding and decoding. + +```go +// API matches encoding/json for Marshal, Unmarshal, Encode, Decode, etc. +b, err = cbor.Marshal(v) // encode v to []byte b +err = cbor.Unmarshal(b, &v) // decode []byte b to v +decoder = cbor.NewDecoder(r) // create decoder with io.Reader r +err = decoder.Decode(&v) // decode a CBOR data item to v + +// v2.5.0 added new functions that return remaining bytes. + +// UnmarshalFirst decodes first CBOR data item and returns remaining bytes. +rest, err = cbor.UnmarshalFirst(b, &v) // decode []byte b to v + +// DiagnoseFirst translates first CBOR data item to text and returns remaining bytes. +text, rest, err = cbor.DiagnoseFirst(b) // decode []byte b to Diagnostic Notation text + +// NOTE: Unmarshal returns ExtraneousDataError if there are remaining bytes, +// but new funcs UnmarshalFirst and DiagnoseFirst do not. +``` + +__IMPORTANT__: 👉 CBOR settings allow trade-offs between speed, security, encoding size, etc. + +- Different CBOR libraries may use different default settings. +- CBOR-based formats or protocols usually require specific settings. + +For example, WebAuthn uses "CTAP2 Canonical CBOR" which is available as a preset. + +### Presets + +Presets can be used as-is or as a starting point for custom settings. + +```go +// EncOptions is a struct of encoder settings. +func CoreDetEncOptions() EncOptions // RFC 8949 Core Deterministic Encoding +func PreferredUnsortedEncOptions() EncOptions // RFC 8949 Preferred Serialization +func CanonicalEncOptions() EncOptions // RFC 7049 Canonical CBOR +func CTAP2EncOptions() EncOptions // FIDO2 CTAP2 Canonical CBOR +``` + +Presets are used to create custom modes. + +### Custom Modes + +Modes are created from settings. Once created, modes have immutable settings. + +💡 Create the mode at startup and reuse it. It is safe for concurrent use. + +```Go +// Create encoding mode. +opts := cbor.CoreDetEncOptions() // use preset options as a starting point +opts.Time = cbor.TimeUnix // change any settings if needed +em, err := opts.EncMode() // create an immutable encoding mode + +// Reuse the encoding mode. It is safe for concurrent use. + +// API matches encoding/json. +b, err := em.Marshal(v) // encode v to []byte b +encoder := em.NewEncoder(w) // create encoder with io.Writer w +err := encoder.Encode(v) // encode v to io.Writer w +``` + +Default mode and custom modes automatically apply struct tags. + +### Struct Tags + +Struct tags (`toarray`, `keyasint`, `omitempty`) reduce encoded size of structs. + +
Example encoding 3-level nested Go struct to 1 byte CBOR

+ +https://go.dev/play/p/YxwvfPdFQG2 + +```Go +// Example encoding nested struct (with omitempty tag) +// - encoding/json: 18 byte JSON +// - fxamacker/cbor: 1 byte CBOR +package main + +import ( + "encoding/hex" + "encoding/json" + "fmt" + + "github.com/fxamacker/cbor/v2" +) + +type GrandChild struct { + Quux int `json:",omitempty"` +} + +type Child struct { + Baz int `json:",omitempty"` + Qux GrandChild `json:",omitempty"` +} + +type Parent struct { + Foo Child `json:",omitempty"` + Bar int `json:",omitempty"` +} + +func cb() { + results, _ := cbor.Marshal(Parent{}) + fmt.Println("hex(CBOR): " + hex.EncodeToString(results)) + + text, _ := cbor.Diagnose(results) // Diagnostic Notation + fmt.Println("DN: " + text) +} + +func js() { + results, _ := json.Marshal(Parent{}) + fmt.Println("hex(JSON): " + hex.EncodeToString(results)) + + text := string(results) // JSON + fmt.Println("JSON: " + text) +} + +func main() { + cb() + fmt.Println("-------------") + js() +} +``` + +Output (DN is Diagnostic Notation): +``` +hex(CBOR): a0 +DN: {} +------------- +hex(JSON): 7b22466f6f223a7b22517578223a7b7d7d7d +JSON: {"Foo":{"Qux":{}}} +``` + +


+ +
+ +
Example using several struct tags

+ +![alt text](https://github.com/fxamacker/images/raw/master/cbor/v2.3.0/cbor_struct_tags_api.svg?sanitize=1 "CBOR API and Go Struct Tags") + +

+ +Struct tags simplify use of CBOR-based protocols that require CBOR arrays or maps with integer keys. + +### CBOR Tags + +CBOR tags are specified in a `TagSet`. + +Custom modes can be created with a `TagSet` to handle CBOR tags. + +```go +em, err := opts.EncMode() // no CBOR tags +em, err := opts.EncModeWithTags(ts) // immutable CBOR tags +em, err := opts.EncModeWithSharedTags(ts) // mutable shared CBOR tags +``` + +`TagSet` and modes using it are safe for concurrent use. Equivalent API is available for `DecMode`. + +
Example using TagSet and TagOptions

+ +```go +// Use signedCWT struct defined in "Decoding CWT" example. + +// Create TagSet (safe for concurrency). +tags := cbor.NewTagSet() +// Register tag COSE_Sign1 18 with signedCWT type. +tags.Add( + cbor.TagOptions{EncTag: cbor.EncTagRequired, DecTag: cbor.DecTagRequired}, + reflect.TypeOf(signedCWT{}), + 18) + +// Create DecMode with immutable tags. +dm, _ := cbor.DecOptions{}.DecModeWithTags(tags) + +// Unmarshal to signedCWT with tag support. +var v signedCWT +if err := dm.Unmarshal(data, &v); err != nil { + return err +} + +// Create EncMode with immutable tags. +em, _ := cbor.EncOptions{}.EncModeWithTags(tags) + +// Marshal signedCWT with tag number. +if data, err := cbor.Marshal(v); err != nil { + return err +} +``` + +

+ +### Functions and Interfaces + +
Functions and interfaces at a glance

+ +Common functions with same API as `encoding/json`: +- `Marshal`, `Unmarshal` +- `NewEncoder`, `(*Encoder).Encode` +- `NewDecoder`, `(*Decoder).Decode` + +NOTE: `Unmarshal` will return `ExtraneousDataError` if there are remaining bytes +because RFC 8949 treats CBOR data item with remaining bytes as malformed. +- 💡 Use `UnmarshalFirst` to decode first CBOR data item and return any remaining bytes. + +Other useful functions: +- `Diagnose`, `DiagnoseFirst` produce human-readable [Extended Diagnostic Notation](https://www.rfc-editor.org/rfc/rfc8610.html#appendix-G) from CBOR data. +- `UnmarshalFirst` decodes first CBOR data item and return any remaining bytes. +- `Wellformed` returns true if the the CBOR data item is well-formed. + +Interfaces identical or comparable to Go `encoding` packages include: +`Marshaler`, `Unmarshaler`, `BinaryMarshaler`, and `BinaryUnmarshaler`. + +The `RawMessage` type can be used to delay CBOR decoding or precompute CBOR encoding. + +

+ +### Security Tips + +🔒 Use Go's `io.LimitReader` to limit size when decoding very large or indefinite size data. + +Default limits may need to be increased for systems handling very large data (e.g. blockchains). + +`DecOptions` can be used to modify default limits for `MaxArrayElements`, `MaxMapPairs`, and `MaxNestedLevels`. + +## Status + +v2.6.0 (February 2024) adds important new features, optimizations, and bug fixes. It is especially useful to systems that need to convert data between CBOR and JSON. New options and optimizations improve handling of bignum, integers, maps, and strings. + +For more details, see [release notes](https://github.com/fxamacker/cbor/releases). + +### Prior Release + +v2.5.0 was released on Sunday, August 13, 2023 with new features and important bug fixes. It is fuzz tested and production quality after extended beta [v2.5.0-beta](https://github.com/fxamacker/cbor/releases/tag/v2.5.0-beta) (Dec 2022) -> [v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) (Aug 2023). + +__IMPORTANT__: 👉 Before upgrading from v2.4 or older release, please read the notable changes highlighted in the release notes. v2.5.0 is a large release with bug fixes to error handling for extraneous data in `Unmarshal`, etc. that should be reviewed before upgrading. + +See [v2.5.0 release notes](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) for list of new features, improvements, and bug fixes. + +See ["Version and API Changes"](https://github.com/fxamacker/cbor#versions-and-api-changes) section for more info about version numbering, etc. + + + +## Who uses fxamacker/cbor + +`fxamacker/cbor` is used in projects by Arm Ltd., Berlin Institute of Health at Charité, Chainlink, Cisco, Confidential Computing Consortium, ConsenSys, Dapper Labs, EdgeX Foundry, F5, FIDO Alliance, Fraunhofer‑AISEC, Let's Encrypt (ISRG), Linux Foundation, Matrix.org, Microsoft, Mozilla, National Cybersecurity Agency of France (govt), Netherlands (govt), Oasis Protocol, Smallstep, Tailscale, Taurus SA, Teleport, TIBCO, and others. + +`fxamacker/cbor` passed multiple confidential security assessments. A [nonconfidential security assessment](https://github.com/veraison/go-cose/blob/v1.0.0-rc.1/reports/NCC_Microsoft-go-cose-Report_2022-05-26_v1.0.pdf) (prepared by NCC Group for Microsoft Corporation) includes a subset of fxamacker/cbor v2.4.0 in its scope. + +## Standards + +`fxamacker/cbor` is a CBOR codec in full conformance with [IETF STD 94 (RFC 8949)](https://www.rfc-editor.org/info/std94). It also supports CBOR Sequences ([RFC 8742](https://www.rfc-editor.org/rfc/rfc8742.html)) and Extended Diagnostic Notation ([Appendix G of RFC 8610](https://www.rfc-editor.org/rfc/rfc8610.html#appendix-G)). + +Notable CBOR features include: + +| CBOR Feature | Description | +| :--- | :--- | +| CBOR tags | API supports built-in and user-defined tags. | +| Preferred serialization | Integers encode to fewest bytes. Optional float64 → float32 → float16. | +| Map key sorting | Unsorted, length-first (Canonical CBOR), and bytewise-lexicographic (CTAP2). | +| Duplicate map keys | Always forbid for encoding and option to allow/forbid for decoding. | +| Indefinite length data | Option to allow/forbid for encoding and decoding. | +| Well-formedness | Always checked and enforced. | +| Basic validity checks | Optionally check UTF-8 validity and duplicate map keys. | +| Security considerations | Prevent integer overflow and resource exhaustion (RFC 8949 Section 10). | + +Known limitations are noted in the [Limitations section](#limitations). + +Go nil values for slices, maps, pointers, etc. are encoded as CBOR null. Empty slices, maps, etc. are encoded as empty CBOR arrays and maps. + +Decoder checks for all required well-formedness errors, including all "subkinds" of syntax errors and too little data. + +After well-formedness is verified, basic validity errors are handled as follows: + +* Invalid UTF-8 string: Decoder has option to check and return invalid UTF-8 string error. This check is enabled by default. +* Duplicate keys in a map: Decoder has options to ignore or enforce rejection of duplicate map keys. + +When decoding well-formed CBOR arrays and maps, decoder saves the first error it encounters and continues with the next item. Options to handle this differently may be added in the future. + +By default, decoder treats time values of floating-point NaN and Infinity as if they are CBOR Null or CBOR Undefined. + +__Click to expand topic:__ + +
+ Duplicate Map Keys

+ +This library provides options for fast detection and rejection of duplicate map keys based on applying a Go-specific data model to CBOR's extended generic data model in order to determine duplicate vs distinct map keys. Detection relies on whether the CBOR map key would be a duplicate "key" when decoded and applied to the user-provided Go map or struct. + +`DupMapKeyQuiet` turns off detection of duplicate map keys. It tries to use a "keep fastest" method by choosing either "keep first" or "keep last" depending on the Go data type. + +`DupMapKeyEnforcedAPF` enforces detection and rejection of duplidate map keys. Decoding stops immediately and returns `DupMapKeyError` when the first duplicate key is detected. The error includes the duplicate map key and the index number. + +APF suffix means "Allow Partial Fill" so the destination map or struct can contain some decoded values at the time of error. It is the caller's responsibility to respond to the `DupMapKeyError` by discarding the partially filled result if that's required by their protocol. + +

+ +
+ Tag Validity

+ +This library checks tag validity for built-in tags (currently tag numbers 0, 1, 2, 3, and 55799): + +* Inadmissible type for tag content +* Inadmissible value for tag content + +Unknown tag data items (not tag number 0, 1, 2, 3, or 55799) are handled in two ways: + +* When decoding into an empty interface, unknown tag data item will be decoded into `cbor.Tag` data type, which contains tag number and tag content. The tag content will be decoded into the default Go data type for the CBOR data type. +* When decoding into other Go types, unknown tag data item is decoded into the specified Go type. If Go type is registered with a tag number, the tag number can optionally be verified. + +Decoder also has an option to forbid tag data items (treat any tag data item as error) which is specified by protocols such as CTAP2 Canonical CBOR. + +For more information, see [decoding options](#decoding-options-1) and [tag options](#tag-options). + +

+ +## Limitations + +If any of these limitations prevent you from using this library, please open an issue along with a link to your project. + +* CBOR `Undefined` (0xf7) value decodes to Go's `nil` value. CBOR `Null` (0xf6) more closely matches Go's `nil`. +* CBOR map keys with data types not supported by Go for map keys are ignored and an error is returned after continuing to decode remaining items. +* When decoding registered CBOR tag data to interface type, decoder creates a pointer to registered Go type matching CBOR tag number. Requiring a pointer for this is a Go limitation. + +## Fuzzing and Code Coverage + +__Code coverage__ is always 95% or higher (with `go test -cover`) when tagging a release. + +__Coverage-guided fuzzing__ must pass billions of execs using before tagging a release. Fuzzing is done using nonpublic code which may eventually get merged into this project. Until then, reports like OpenSSF Scorecard can't detect fuzz tests being used by this project. + +
+ +## Versions and API Changes +This project uses [Semantic Versioning](https://semver.org), so the API is always backwards compatible unless the major version number changes. + +These functions have signatures identical to encoding/json and their API will continue to match `encoding/json` even after major new releases: +`Marshal`, `Unmarshal`, `NewEncoder`, `NewDecoder`, `(*Encoder).Encode`, and `(*Decoder).Decode`. + +Exclusions from SemVer: +- Newly added API documented as "subject to change". +- Newly added API in the master branch that has never been tagged in non-beta release. +- If function parameters are unchanged, bug fixes that change behavior (e.g. return error for edge case was missed in prior version). We try to highlight these in the release notes and add extended beta period. E.g. [v2.5.0-beta](https://github.com/fxamacker/cbor/releases/tag/v2.5.0-beta) (Dec 2022) -> [v2.5.0](https://github.com/fxamacker/cbor/releases/tag/v2.5.0) (Aug 2023). + +This project avoids breaking changes to behavior of encoding and decoding functions unless required to improve conformance with supported RFCs (e.g. RFC 8949, RFC 8742, etc.) Visible changes that don't improve conformance to standards are typically made available as new opt-in settings or new functions. + +## Code of Conduct + +This project has adopted the [Contributor Covenant Code of Conduct](CODE_OF_CONDUCT.md). Contact [faye.github@gmail.com](mailto:faye.github@gmail.com) with any questions or comments. + +## Contributing + +Please open an issue before beginning work on a PR. The improvement may have already been considered, etc. + +For more info, see [How to Contribute](CONTRIBUTING.md). + +## Security Policy + +Security fixes are provided for the latest released version of fxamacker/cbor. + +For the full text of the Security Policy, see [SECURITY.md](SECURITY.md). + +## Acknowledgements + +Many thanks to all the contributors on this project! + +I'm especially grateful to Bastian Müller and Dieter Shirley for suggesting and collaborating on CBOR stream mode, and much more. + +I'm very grateful to Stefan Tatschner, Yawning Angel, Jernej Kos, x448, ZenGround0, and Jakob Borg for their contributions or support in the very early days. + +This library clearly wouldn't be possible without Carsten Bormann authoring CBOR RFCs. + +Special thanks to Laurence Lundblade and Jeffrey Yasskin for their help on IETF mailing list or at [7049bis](https://github.com/cbor-wg/CBORbis). + +Huge thanks to The Go Authors for creating a fun and practical programming language with batteries included! + +This library uses `x448/float16` which used to be included. As a standalone package, `x448/float16` is useful to other projects as well. + +## License + +Copyright © 2019-2024 [Faye Amacker](https://github.com/fxamacker). + +fxamacker/cbor is licensed under the MIT License. See [LICENSE](LICENSE) for the full license text. + +
diff --git a/vendor/github.com/fxamacker/cbor/v2/SECURITY.md b/vendor/github.com/fxamacker/cbor/v2/SECURITY.md new file mode 100644 index 00000000..9c05146d --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/SECURITY.md @@ -0,0 +1,7 @@ +# Security Policy + +Security fixes are provided for the latest released version of fxamacker/cbor. + +If the security vulnerability is already known to the public, then you can open an issue as a bug report. + +To report security vulnerabilities not yet known to the public, please email faye.github@gmail.com and allow time for the problem to be resolved before reporting it to the public. diff --git a/vendor/github.com/fxamacker/cbor/v2/bytestring.go b/vendor/github.com/fxamacker/cbor/v2/bytestring.go new file mode 100644 index 00000000..52a28eda --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/bytestring.go @@ -0,0 +1,63 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +package cbor + +import ( + "errors" +) + +// ByteString represents CBOR byte string (major type 2). ByteString can be used +// when using a Go []byte is not possible or convenient. For example, Go doesn't +// allow []byte as map key, so ByteString can be used to support data formats +// having CBOR map with byte string keys. ByteString can also be used to +// encode invalid UTF-8 string as CBOR byte string. +// See DecOption.MapKeyByteStringMode for more details. +type ByteString string + +// Bytes returns bytes representing ByteString. +func (bs ByteString) Bytes() []byte { + return []byte(bs) +} + +// MarshalCBOR encodes ByteString as CBOR byte string (major type 2). +func (bs ByteString) MarshalCBOR() ([]byte, error) { + e := getEncoderBuffer() + defer putEncoderBuffer(e) + + // Encode length + encodeHead(e, byte(cborTypeByteString), uint64(len(bs))) + + // Encode data + buf := make([]byte, e.Len()+len(bs)) + n := copy(buf, e.Bytes()) + copy(buf[n:], bs) + + return buf, nil +} + +// UnmarshalCBOR decodes CBOR byte string (major type 2) to ByteString. +// Decoding CBOR null and CBOR undefined sets ByteString to be empty. +func (bs *ByteString) UnmarshalCBOR(data []byte) error { + if bs == nil { + return errors.New("cbor.ByteString: UnmarshalCBOR on nil pointer") + } + + // Decoding CBOR null and CBOR undefined to ByteString resets data. + // This behavior is similar to decoding CBOR null and CBOR undefined to []byte. + if len(data) == 1 && (data[0] == 0xf6 || data[0] == 0xf7) { + *bs = "" + return nil + } + + d := decoder{data: data, dm: defaultDecMode} + + // Check if CBOR data type is byte string + if typ := d.nextCBORType(); typ != cborTypeByteString { + return &UnmarshalTypeError{CBORType: typ.String(), GoType: typeByteString.String()} + } + + b, _ := d.parseByteString() + *bs = ByteString(b) + return nil +} diff --git a/vendor/github.com/fxamacker/cbor/v2/cache.go b/vendor/github.com/fxamacker/cbor/v2/cache.go new file mode 100644 index 00000000..8a4a5c87 --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/cache.go @@ -0,0 +1,324 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +package cbor + +import ( + "bytes" + "errors" + "reflect" + "sort" + "strconv" + "strings" + "sync" +) + +type encodeFuncs struct { + ef encodeFunc + ief isEmptyFunc +} + +var ( + decodingStructTypeCache sync.Map // map[reflect.Type]*decodingStructType + encodingStructTypeCache sync.Map // map[reflect.Type]*encodingStructType + encodeFuncCache sync.Map // map[reflect.Type]encodeFuncs + typeInfoCache sync.Map // map[reflect.Type]*typeInfo +) + +type specialType int + +const ( + specialTypeNone specialType = iota + specialTypeUnmarshalerIface + specialTypeEmptyIface + specialTypeIface + specialTypeTag + specialTypeTime +) + +type typeInfo struct { + elemTypeInfo *typeInfo + keyTypeInfo *typeInfo + typ reflect.Type + kind reflect.Kind + nonPtrType reflect.Type + nonPtrKind reflect.Kind + spclType specialType +} + +func newTypeInfo(t reflect.Type) *typeInfo { + tInfo := typeInfo{typ: t, kind: t.Kind()} + + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + + k := t.Kind() + + tInfo.nonPtrType = t + tInfo.nonPtrKind = k + + if k == reflect.Interface { + if t.NumMethod() == 0 { + tInfo.spclType = specialTypeEmptyIface + } else { + tInfo.spclType = specialTypeIface + } + } else if t == typeTag { + tInfo.spclType = specialTypeTag + } else if t == typeTime { + tInfo.spclType = specialTypeTime + } else if reflect.PtrTo(t).Implements(typeUnmarshaler) { + tInfo.spclType = specialTypeUnmarshalerIface + } + + switch k { + case reflect.Array, reflect.Slice: + tInfo.elemTypeInfo = getTypeInfo(t.Elem()) + case reflect.Map: + tInfo.keyTypeInfo = getTypeInfo(t.Key()) + tInfo.elemTypeInfo = getTypeInfo(t.Elem()) + } + + return &tInfo +} + +type decodingStructType struct { + fields fields + err error + toArray bool +} + +func getDecodingStructType(t reflect.Type) *decodingStructType { + if v, _ := decodingStructTypeCache.Load(t); v != nil { + return v.(*decodingStructType) + } + + flds, structOptions := getFields(t) + + toArray := hasToArrayOption(structOptions) + + var err error + for i := 0; i < len(flds); i++ { + if flds[i].keyAsInt { + nameAsInt, numErr := strconv.Atoi(flds[i].name) + if numErr != nil { + err = errors.New("cbor: failed to parse field name \"" + flds[i].name + "\" to int (" + numErr.Error() + ")") + break + } + flds[i].nameAsInt = int64(nameAsInt) + } + + flds[i].typInfo = getTypeInfo(flds[i].typ) + } + + structType := &decodingStructType{fields: flds, err: err, toArray: toArray} + decodingStructTypeCache.Store(t, structType) + return structType +} + +type encodingStructType struct { + fields fields + bytewiseFields fields + lengthFirstFields fields + omitEmptyFieldsIdx []int + err error + toArray bool + fixedLength bool // Struct type doesn't have any omitempty or anonymous fields. +} + +func (st *encodingStructType) getFields(em *encMode) fields { + if em.sort == SortNone { + return st.fields + } + if em.sort == SortLengthFirst { + return st.lengthFirstFields + } + return st.bytewiseFields +} + +type bytewiseFieldSorter struct { + fields fields +} + +func (x *bytewiseFieldSorter) Len() int { + return len(x.fields) +} + +func (x *bytewiseFieldSorter) Swap(i, j int) { + x.fields[i], x.fields[j] = x.fields[j], x.fields[i] +} + +func (x *bytewiseFieldSorter) Less(i, j int) bool { + return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) <= 0 +} + +type lengthFirstFieldSorter struct { + fields fields +} + +func (x *lengthFirstFieldSorter) Len() int { + return len(x.fields) +} + +func (x *lengthFirstFieldSorter) Swap(i, j int) { + x.fields[i], x.fields[j] = x.fields[j], x.fields[i] +} + +func (x *lengthFirstFieldSorter) Less(i, j int) bool { + if len(x.fields[i].cborName) != len(x.fields[j].cborName) { + return len(x.fields[i].cborName) < len(x.fields[j].cborName) + } + return bytes.Compare(x.fields[i].cborName, x.fields[j].cborName) <= 0 +} + +func getEncodingStructType(t reflect.Type) (*encodingStructType, error) { + if v, _ := encodingStructTypeCache.Load(t); v != nil { + structType := v.(*encodingStructType) + return structType, structType.err + } + + flds, structOptions := getFields(t) + + if hasToArrayOption(structOptions) { + return getEncodingStructToArrayType(t, flds) + } + + var err error + var hasKeyAsInt bool + var hasKeyAsStr bool + var omitEmptyIdx []int + fixedLength := true + e := getEncoderBuffer() + for i := 0; i < len(flds); i++ { + // Get field's encodeFunc + flds[i].ef, flds[i].ief = getEncodeFunc(flds[i].typ) + if flds[i].ef == nil { + err = &UnsupportedTypeError{t} + break + } + + // Encode field name + if flds[i].keyAsInt { + nameAsInt, numErr := strconv.Atoi(flds[i].name) + if numErr != nil { + err = errors.New("cbor: failed to parse field name \"" + flds[i].name + "\" to int (" + numErr.Error() + ")") + break + } + flds[i].nameAsInt = int64(nameAsInt) + if nameAsInt >= 0 { + encodeHead(e, byte(cborTypePositiveInt), uint64(nameAsInt)) + } else { + n := nameAsInt*(-1) - 1 + encodeHead(e, byte(cborTypeNegativeInt), uint64(n)) + } + flds[i].cborName = make([]byte, e.Len()) + copy(flds[i].cborName, e.Bytes()) + e.Reset() + + hasKeyAsInt = true + } else { + encodeHead(e, byte(cborTypeTextString), uint64(len(flds[i].name))) + flds[i].cborName = make([]byte, e.Len()+len(flds[i].name)) + n := copy(flds[i].cborName, e.Bytes()) + copy(flds[i].cborName[n:], flds[i].name) + e.Reset() + + // If cborName contains a text string, then cborNameByteString contains a + // string that has the byte string major type but is otherwise identical to + // cborName. + flds[i].cborNameByteString = make([]byte, len(flds[i].cborName)) + copy(flds[i].cborNameByteString, flds[i].cborName) + // Reset encoded CBOR type to byte string, preserving the "additional + // information" bits: + flds[i].cborNameByteString[0] = byte(cborTypeByteString) | (flds[i].cborNameByteString[0] & 0x1f) + + hasKeyAsStr = true + } + + // Check if field is from embedded struct + if len(flds[i].idx) > 1 { + fixedLength = false + } + + // Check if field can be omitted when empty + if flds[i].omitEmpty { + fixedLength = false + omitEmptyIdx = append(omitEmptyIdx, i) + } + } + putEncoderBuffer(e) + + if err != nil { + structType := &encodingStructType{err: err} + encodingStructTypeCache.Store(t, structType) + return structType, structType.err + } + + // Sort fields by canonical order + bytewiseFields := make(fields, len(flds)) + copy(bytewiseFields, flds) + sort.Sort(&bytewiseFieldSorter{bytewiseFields}) + + lengthFirstFields := bytewiseFields + if hasKeyAsInt && hasKeyAsStr { + lengthFirstFields = make(fields, len(flds)) + copy(lengthFirstFields, flds) + sort.Sort(&lengthFirstFieldSorter{lengthFirstFields}) + } + + structType := &encodingStructType{ + fields: flds, + bytewiseFields: bytewiseFields, + lengthFirstFields: lengthFirstFields, + omitEmptyFieldsIdx: omitEmptyIdx, + fixedLength: fixedLength, + } + encodingStructTypeCache.Store(t, structType) + return structType, structType.err +} + +func getEncodingStructToArrayType(t reflect.Type, flds fields) (*encodingStructType, error) { + for i := 0; i < len(flds); i++ { + // Get field's encodeFunc + flds[i].ef, flds[i].ief = getEncodeFunc(flds[i].typ) + if flds[i].ef == nil { + structType := &encodingStructType{err: &UnsupportedTypeError{t}} + encodingStructTypeCache.Store(t, structType) + return structType, structType.err + } + } + + structType := &encodingStructType{ + fields: flds, + toArray: true, + fixedLength: true, + } + encodingStructTypeCache.Store(t, structType) + return structType, structType.err +} + +func getEncodeFunc(t reflect.Type) (encodeFunc, isEmptyFunc) { + if v, _ := encodeFuncCache.Load(t); v != nil { + fs := v.(encodeFuncs) + return fs.ef, fs.ief + } + ef, ief := getEncodeFuncInternal(t) + encodeFuncCache.Store(t, encodeFuncs{ef, ief}) + return ef, ief +} + +func getTypeInfo(t reflect.Type) *typeInfo { + if v, _ := typeInfoCache.Load(t); v != nil { + return v.(*typeInfo) + } + tInfo := newTypeInfo(t) + typeInfoCache.Store(t, tInfo) + return tInfo +} + +func hasToArrayOption(tag string) bool { + s := ",toarray" + idx := strings.Index(tag, s) + return idx >= 0 && (len(tag) == idx+len(s) || tag[idx+len(s)] == ',') +} diff --git a/vendor/github.com/fxamacker/cbor/v2/decode.go b/vendor/github.com/fxamacker/cbor/v2/decode.go new file mode 100644 index 00000000..0b44124d --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/decode.go @@ -0,0 +1,2440 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +package cbor + +import ( + "encoding" + "encoding/binary" + "errors" + "fmt" + "io" + "math" + "math/big" + "reflect" + "strconv" + "strings" + "time" + "unicode/utf8" + + "github.com/x448/float16" +) + +// Unmarshal parses the CBOR-encoded data into the value pointed to by v +// using default decoding options. If v is nil, not a pointer, or +// a nil pointer, Unmarshal returns an error. +// +// To unmarshal CBOR into a value implementing the Unmarshaler interface, +// Unmarshal calls that value's UnmarshalCBOR method with a valid +// CBOR value. +// +// To unmarshal CBOR byte string into a value implementing the +// encoding.BinaryUnmarshaler interface, Unmarshal calls that value's +// UnmarshalBinary method with decoded CBOR byte string. +// +// To unmarshal CBOR into a pointer, Unmarshal sets the pointer to nil +// if CBOR data is null (0xf6) or undefined (0xf7). Otherwise, Unmarshal +// unmarshals CBOR into the value pointed to by the pointer. If the +// pointer is nil, Unmarshal creates a new value for it to point to. +// +// To unmarshal CBOR into an empty interface value, Unmarshal uses the +// following rules: +// +// CBOR booleans decode to bool. +// CBOR positive integers decode to uint64. +// CBOR negative integers decode to int64 (big.Int if value overflows). +// CBOR floating points decode to float64. +// CBOR byte strings decode to []byte. +// CBOR text strings decode to string. +// CBOR arrays decode to []interface{}. +// CBOR maps decode to map[interface{}]interface{}. +// CBOR null and undefined values decode to nil. +// CBOR times (tag 0 and 1) decode to time.Time. +// CBOR bignums (tag 2 and 3) decode to big.Int. +// CBOR tags with an unrecognized number decode to cbor.Tag +// +// To unmarshal a CBOR array into a slice, Unmarshal allocates a new slice +// if the CBOR array is empty or slice capacity is less than CBOR array length. +// Otherwise Unmarshal overwrites existing elements, and sets slice length +// to CBOR array length. +// +// To unmarshal a CBOR array into a Go array, Unmarshal decodes CBOR array +// elements into Go array elements. If the Go array is smaller than the +// CBOR array, the extra CBOR array elements are discarded. If the CBOR +// array is smaller than the Go array, the extra Go array elements are +// set to zero values. +// +// To unmarshal a CBOR array into a struct, struct must have a special field "_" +// with struct tag `cbor:",toarray"`. Go array elements are decoded into struct +// fields. Any "omitempty" struct field tag option is ignored in this case. +// +// To unmarshal a CBOR map into a map, Unmarshal allocates a new map only if the +// map is nil. Otherwise Unmarshal reuses the existing map and keeps existing +// entries. Unmarshal stores key-value pairs from the CBOR map into Go map. +// See DecOptions.DupMapKey to enable duplicate map key detection. +// +// To unmarshal a CBOR map into a struct, Unmarshal matches CBOR map keys to the +// keys in the following priority: +// +// 1. "cbor" key in struct field tag, +// 2. "json" key in struct field tag, +// 3. struct field name. +// +// Unmarshal tries an exact match for field name, then a case-insensitive match. +// Map key-value pairs without corresponding struct fields are ignored. See +// DecOptions.ExtraReturnErrors to return error at unknown field. +// +// To unmarshal a CBOR text string into a time.Time value, Unmarshal parses text +// string formatted in RFC3339. To unmarshal a CBOR integer/float into a +// time.Time value, Unmarshal creates an unix time with integer/float as seconds +// and fractional seconds since January 1, 1970 UTC. +// +// To unmarshal CBOR null (0xf6) and undefined (0xf7) values into a +// slice/map/pointer, Unmarshal sets Go value to nil. Because null is often +// used to mean "not present", unmarshalling CBOR null and undefined value +// into any other Go type has no effect and returns no error. +// +// Unmarshal supports CBOR tag 55799 (self-describe CBOR), tag 0 and 1 (time), +// and tag 2 and 3 (bignum). +// +// Unmarshal returns ExtraneousDataError error (without decoding into v) +// if there are any remaining bytes following the first valid CBOR data item. +// See UnmarshalFirst, if you want to unmarshal only the first +// CBOR data item without ExtraneousDataError caused by remaining bytes. +func Unmarshal(data []byte, v interface{}) error { + return defaultDecMode.Unmarshal(data, v) +} + +// UnmarshalFirst parses the first CBOR data item into the value pointed to by v +// using default decoding options. Any remaining bytes are returned in rest. +// +// If v is nil, not a pointer, or a nil pointer, UnmarshalFirst returns an error. +// +// See the documentation for Unmarshal for details. +func UnmarshalFirst(data []byte, v interface{}) (rest []byte, err error) { + return defaultDecMode.UnmarshalFirst(data, v) +} + +// Valid checks whether data is a well-formed encoded CBOR data item and +// that it complies with default restrictions such as MaxNestedLevels, +// MaxArrayElements, MaxMapPairs, etc. +// +// If there are any remaining bytes after the CBOR data item, +// an ExtraneousDataError is returned. +// +// WARNING: Valid doesn't check if encoded CBOR data item is valid (i.e. validity) +// and RFC 8949 distinctly defines what is "Valid" and what is "Well-formed". +// +// Deprecated: Valid is kept for compatibility and should not be used. +// Use Wellformed instead because it has a more appropriate name. +func Valid(data []byte) error { + return defaultDecMode.Valid(data) +} + +// Wellformed checks whether data is a well-formed encoded CBOR data item and +// that it complies with default restrictions such as MaxNestedLevels, +// MaxArrayElements, MaxMapPairs, etc. +// +// If there are any remaining bytes after the CBOR data item, +// an ExtraneousDataError is returned. +func Wellformed(data []byte) error { + return defaultDecMode.Wellformed(data) +} + +// Unmarshaler is the interface implemented by types that wish to unmarshal +// CBOR data themselves. The input is a valid CBOR value. UnmarshalCBOR +// must copy the CBOR data if it needs to use it after returning. +type Unmarshaler interface { + UnmarshalCBOR([]byte) error +} + +// InvalidUnmarshalError describes an invalid argument passed to Unmarshal. +type InvalidUnmarshalError struct { + s string +} + +func (e *InvalidUnmarshalError) Error() string { + return e.s +} + +// UnmarshalTypeError describes a CBOR value that can't be decoded to a Go type. +type UnmarshalTypeError struct { + CBORType string // type of CBOR value + GoType string // type of Go value it could not be decoded into + StructFieldName string // name of the struct field holding the Go value (optional) + errorMsg string // additional error message (optional) +} + +func (e *UnmarshalTypeError) Error() string { + var s string + if e.StructFieldName != "" { + s = "cbor: cannot unmarshal " + e.CBORType + " into Go struct field " + e.StructFieldName + " of type " + e.GoType + } else { + s = "cbor: cannot unmarshal " + e.CBORType + " into Go value of type " + e.GoType + } + if e.errorMsg != "" { + s += " (" + e.errorMsg + ")" + } + return s +} + +// InvalidMapKeyTypeError describes invalid Go map key type when decoding CBOR map. +// For example, Go doesn't allow slice as map key. +type InvalidMapKeyTypeError struct { + GoType string +} + +func (e *InvalidMapKeyTypeError) Error() string { + return "cbor: invalid map key type: " + e.GoType +} + +// DupMapKeyError describes detected duplicate map key in CBOR map. +type DupMapKeyError struct { + Key interface{} + Index int +} + +func (e *DupMapKeyError) Error() string { + return fmt.Sprintf("cbor: found duplicate map key \"%v\" at map element index %d", e.Key, e.Index) +} + +// UnknownFieldError describes detected unknown field in CBOR map when decoding to Go struct. +type UnknownFieldError struct { + Index int +} + +func (e *UnknownFieldError) Error() string { + return fmt.Sprintf("cbor: found unknown field at map element index %d", e.Index) +} + +// DupMapKeyMode specifies how to enforce duplicate map key. +type DupMapKeyMode int + +const ( + // DupMapKeyQuiet doesn't enforce duplicate map key. Decoder quietly (no error) + // uses faster of "keep first" or "keep last" depending on Go data type and other factors. + DupMapKeyQuiet DupMapKeyMode = iota + + // DupMapKeyEnforcedAPF enforces detection and rejection of duplicate map keys. + // APF means "Allow Partial Fill" and the destination map or struct can be partially filled. + // If a duplicate map key is detected, DupMapKeyError is returned without further decoding + // of the map. It's the caller's responsibility to respond to DupMapKeyError by + // discarding the partially filled result if their protocol requires it. + // WARNING: using DupMapKeyEnforcedAPF will decrease performance and increase memory use. + DupMapKeyEnforcedAPF + + maxDupMapKeyMode +) + +func (dmkm DupMapKeyMode) valid() bool { + return dmkm >= 0 && dmkm < maxDupMapKeyMode +} + +// IndefLengthMode specifies whether to allow indefinite length items. +type IndefLengthMode int + +const ( + // IndefLengthAllowed allows indefinite length items. + IndefLengthAllowed IndefLengthMode = iota + + // IndefLengthForbidden disallows indefinite length items. + IndefLengthForbidden + + maxIndefLengthMode +) + +func (m IndefLengthMode) valid() bool { + return m >= 0 && m < maxIndefLengthMode +} + +// TagsMode specifies whether to allow CBOR tags. +type TagsMode int + +const ( + // TagsAllowed allows CBOR tags. + TagsAllowed TagsMode = iota + + // TagsForbidden disallows CBOR tags. + TagsForbidden + + maxTagsMode +) + +func (tm TagsMode) valid() bool { + return tm >= 0 && tm < maxTagsMode +} + +// IntDecMode specifies which Go type (int64, uint64, or big.Int) should +// be used when decoding CBOR integers (major type 0 and 1) to Go interface{}. +type IntDecMode int + +const ( + // IntDecConvertNone affects how CBOR integers (major type 0 and 1) decode to Go interface{}. + // It decodes CBOR unsigned integer (major type 0) to: + // - uint64 + // It decodes CBOR negative integer (major type 1) to: + // - int64 if value fits + // - big.Int or *big.Int (see BigIntDecMode) if value doesn't fit into int64 + IntDecConvertNone IntDecMode = iota + + // IntDecConvertSigned affects how CBOR integers (major type 0 and 1) decode to Go interface{}. + // It decodes CBOR integers (major type 0 and 1) to: + // - int64 if value fits + // - big.Int or *big.Int (see BigIntDecMode) if value < math.MinInt64 + // - return UnmarshalTypeError if value > math.MaxInt64 + // Deprecated: IntDecConvertSigned should not be used. + // Please use other options, such as IntDecConvertSignedOrError, IntDecConvertSignedOrBigInt, IntDecConvertNone. + IntDecConvertSigned + + // IntDecConvertSignedOrFail affects how CBOR integers (major type 0 and 1) decode to Go interface{}. + // It decodes CBOR integers (major type 0 and 1) to: + // - int64 if value fits + // - return UnmarshalTypeError if value doesn't fit into int64 + IntDecConvertSignedOrFail + + // IntDecConvertSigned affects how CBOR integers (major type 0 and 1) decode to Go interface{}. + // It makes CBOR integers (major type 0 and 1) decode to: + // - int64 if value fits + // - big.Int or *big.Int (see BigIntDecMode) if value doesn't fit into int64 + IntDecConvertSignedOrBigInt + + maxIntDec +) + +func (idm IntDecMode) valid() bool { + return idm >= 0 && idm < maxIntDec +} + +// MapKeyByteStringMode specifies how to decode CBOR byte string (major type 2) +// as Go map key when decoding CBOR map key into an empty Go interface value. +// Specifically, this option applies when decoding CBOR map into +// - Go empty interface, or +// - Go map with empty interface as key type. +// The CBOR map key types handled by this option are +// - byte string +// - tagged byte string +// - nested tagged byte string +type MapKeyByteStringMode int + +const ( + // MapKeyByteStringAllowed allows CBOR byte string to be decoded as Go map key. + // Since Go doesn't allow []byte as map key, CBOR byte string is decoded to + // ByteString which has underlying string type. + // This is the default setting. + MapKeyByteStringAllowed MapKeyByteStringMode = iota + + // MapKeyByteStringForbidden forbids CBOR byte string being decoded as Go map key. + // Attempting to decode CBOR byte string as map key into empty interface value + // returns a decoding error. + MapKeyByteStringForbidden + + maxMapKeyByteStringMode +) + +func (mkbsm MapKeyByteStringMode) valid() bool { + return mkbsm >= 0 && mkbsm < maxMapKeyByteStringMode +} + +// ExtraDecErrorCond specifies extra conditions that should be treated as errors. +type ExtraDecErrorCond uint + +// ExtraDecErrorNone indicates no extra error condition. +const ExtraDecErrorNone ExtraDecErrorCond = 0 + +const ( + // ExtraDecErrorUnknownField indicates error condition when destination + // Go struct doesn't have a field matching a CBOR map key. + ExtraDecErrorUnknownField ExtraDecErrorCond = 1 << iota + + maxExtraDecError +) + +func (ec ExtraDecErrorCond) valid() bool { + return ec < maxExtraDecError +} + +// UTF8Mode option specifies if decoder should +// decode CBOR Text containing invalid UTF-8 string. +type UTF8Mode int + +const ( + // UTF8RejectInvalid rejects CBOR Text containing + // invalid UTF-8 string. + UTF8RejectInvalid UTF8Mode = iota + + // UTF8DecodeInvalid allows decoding CBOR Text containing + // invalid UTF-8 string. + UTF8DecodeInvalid + + maxUTF8Mode +) + +func (um UTF8Mode) valid() bool { + return um >= 0 && um < maxUTF8Mode +} + +// FieldNameMatchingMode specifies how string keys in CBOR maps are matched to Go struct field names. +type FieldNameMatchingMode int + +const ( + // FieldNameMatchingPreferCaseSensitive prefers to decode map items into struct fields whose names (or tag + // names) exactly match the item's key. If there is no such field, a map item will be decoded into a field whose + // name is a case-insensitive match for the item's key. + FieldNameMatchingPreferCaseSensitive FieldNameMatchingMode = iota + + // FieldNameMatchingCaseSensitive decodes map items only into a struct field whose name (or tag name) is an + // exact match for the item's key. + FieldNameMatchingCaseSensitive + + maxFieldNameMatchingMode +) + +func (fnmm FieldNameMatchingMode) valid() bool { + return fnmm >= 0 && fnmm < maxFieldNameMatchingMode +} + +// BigIntDecMode specifies how to decode CBOR bignum to Go interface{}. +type BigIntDecMode int + +const ( + // BigIntDecodeValue makes CBOR bignum decode to big.Int (instead of *big.Int) + // when unmarshalling into a Go interface{}. + BigIntDecodeValue BigIntDecMode = iota + + // BigIntDecodePointer makes CBOR bignum decode to *big.Int when + // unmarshalling into a Go interface{}. + BigIntDecodePointer + + maxBigIntDecMode +) + +func (bidm BigIntDecMode) valid() bool { + return bidm >= 0 && bidm < maxBigIntDecMode +} + +// ByteStringToStringMode specifies the behavior when decoding a CBOR byte string into a Go string. +type ByteStringToStringMode int + +const ( + // ByteStringToStringForbidden generates an error on an attempt to decode a CBOR byte string into a Go string. + ByteStringToStringForbidden ByteStringToStringMode = iota + + // ByteStringToStringAllowed permits decoding a CBOR byte string into a Go string. + ByteStringToStringAllowed + + maxByteStringToStringMode +) + +func (bstsm ByteStringToStringMode) valid() bool { + return bstsm >= 0 && bstsm < maxByteStringToStringMode +} + +// FieldNameByteStringMode specifies the behavior when decoding a CBOR byte string map key as a Go struct field name. +type FieldNameByteStringMode int + +const ( + // FieldNameByteStringForbidden generates an error on an attempt to decode a CBOR byte string map key as a Go struct field name. + FieldNameByteStringForbidden FieldNameByteStringMode = iota + + // FieldNameByteStringAllowed permits CBOR byte string map keys to be recognized as Go struct field names. + FieldNameByteStringAllowed + + maxFieldNameByteStringMode +) + +func (fnbsm FieldNameByteStringMode) valid() bool { + return fnbsm >= 0 && fnbsm < maxFieldNameByteStringMode +} + +// UnrecognizedTagToAnyMode specifies how to decode unrecognized CBOR tag into an empty interface (any). +// Currently, recognized CBOR tag numbers are 0, 1, 2, 3, or registered by TagSet. +type UnrecognizedTagToAnyMode int + +const ( + // UnrecognizedTagNumAndContentToAny decodes CBOR tag number and tag content to cbor.Tag + // when decoding unrecognized CBOR tag into an empty interface. + UnrecognizedTagNumAndContentToAny UnrecognizedTagToAnyMode = iota + + // UnrecognizedTagContentToAny decodes only CBOR tag content (into its default type) + // when decoding unrecognized CBOR tag into an empty interface. + UnrecognizedTagContentToAny + + maxUnrecognizedTagToAny +) + +func (uttam UnrecognizedTagToAnyMode) valid() bool { + return uttam >= 0 && uttam < maxUnrecognizedTagToAny +} + +// DecOptions specifies decoding options. +type DecOptions struct { + // DupMapKey specifies whether to enforce duplicate map key. + DupMapKey DupMapKeyMode + + // TimeTag specifies whether to check validity of time.Time (e.g. valid tag number and tag content type). + // For now, valid tag number means 0 or 1 as specified in RFC 7049 if the Go type is time.Time. + TimeTag DecTagMode + + // MaxNestedLevels specifies the max nested levels allowed for any combination of CBOR array, maps, and tags. + // Default is 32 levels and it can be set to [4, 65535]. Note that higher maximum levels of nesting can + // require larger amounts of stack to deserialize. Don't increase this higher than you require. + MaxNestedLevels int + + // MaxArrayElements specifies the max number of elements for CBOR arrays. + // Default is 128*1024=131072 and it can be set to [16, 2147483647] + MaxArrayElements int + + // MaxMapPairs specifies the max number of key-value pairs for CBOR maps. + // Default is 128*1024=131072 and it can be set to [16, 2147483647] + MaxMapPairs int + + // IndefLength specifies whether to allow indefinite length CBOR items. + IndefLength IndefLengthMode + + // TagsMd specifies whether to allow CBOR tags (major type 6). + TagsMd TagsMode + + // IntDec specifies which Go integer type (int64 or uint64) to use + // when decoding CBOR int (major type 0 and 1) to Go interface{}. + IntDec IntDecMode + + // MapKeyByteString specifies how to decode CBOR byte string as map key + // when decoding CBOR map with byte string key into an empty interface value. + // By default, an error is returned when attempting to decode CBOR byte string + // as map key because Go doesn't allow []byte as map key. + MapKeyByteString MapKeyByteStringMode + + // ExtraReturnErrors specifies extra conditions that should be treated as errors. + ExtraReturnErrors ExtraDecErrorCond + + // DefaultMapType specifies Go map type to create and decode to + // when unmarshalling CBOR into an empty interface value. + // By default, unmarshal uses map[interface{}]interface{}. + DefaultMapType reflect.Type + + // UTF8 specifies if decoder should decode CBOR Text containing invalid UTF-8. + // By default, unmarshal rejects CBOR text containing invalid UTF-8. + UTF8 UTF8Mode + + // FieldNameMatching specifies how string keys in CBOR maps are matched to Go struct field names. + FieldNameMatching FieldNameMatchingMode + + // BigIntDec specifies how to decode CBOR bignum to Go interface{}. + BigIntDec BigIntDecMode + + // DefaultByteStringType is the Go type that should be produced when decoding a CBOR byte + // string into an empty interface value. Types to which a []byte is convertible are valid + // for this option, except for array and pointer-to-array types. If nil, the default is + // []byte. + DefaultByteStringType reflect.Type + + // ByteStringToString specifies the behavior when decoding a CBOR byte string into a Go string. + ByteStringToString ByteStringToStringMode + + // FieldNameByteString specifies the behavior when decoding a CBOR byte string map key as a + // Go struct field name. + FieldNameByteString FieldNameByteStringMode + + // UnrecognizedTagToAny specifies how to decode unrecognized CBOR tag into an empty interface. + // Currently, recognized CBOR tag numbers are 0, 1, 2, 3, or registered by TagSet. + UnrecognizedTagToAny UnrecognizedTagToAnyMode +} + +// DecMode returns DecMode with immutable options and no tags (safe for concurrency). +func (opts DecOptions) DecMode() (DecMode, error) { + return opts.decMode() +} + +// DecModeWithTags returns DecMode with options and tags that are both immutable (safe for concurrency). +func (opts DecOptions) DecModeWithTags(tags TagSet) (DecMode, error) { + if opts.TagsMd == TagsForbidden { + return nil, errors.New("cbor: cannot create DecMode with TagSet when TagsMd is TagsForbidden") + } + if tags == nil { + return nil, errors.New("cbor: cannot create DecMode with nil value as TagSet") + } + + dm, err := opts.decMode() + if err != nil { + return nil, err + } + + // Copy tags + ts := tagSet(make(map[reflect.Type]*tagItem)) + syncTags := tags.(*syncTagSet) + syncTags.RLock() + for contentType, tag := range syncTags.t { + if tag.opts.DecTag != DecTagIgnored { + ts[contentType] = tag + } + } + syncTags.RUnlock() + + if len(ts) > 0 { + dm.tags = ts + } + + return dm, nil +} + +// DecModeWithSharedTags returns DecMode with immutable options and mutable shared tags (safe for concurrency). +func (opts DecOptions) DecModeWithSharedTags(tags TagSet) (DecMode, error) { + if opts.TagsMd == TagsForbidden { + return nil, errors.New("cbor: cannot create DecMode with TagSet when TagsMd is TagsForbidden") + } + if tags == nil { + return nil, errors.New("cbor: cannot create DecMode with nil value as TagSet") + } + dm, err := opts.decMode() + if err != nil { + return nil, err + } + dm.tags = tags + return dm, nil +} + +const ( + defaultMaxArrayElements = 131072 + minMaxArrayElements = 16 + maxMaxArrayElements = 2147483647 + + defaultMaxMapPairs = 131072 + minMaxMapPairs = 16 + maxMaxMapPairs = 2147483647 +) + +func (opts DecOptions) decMode() (*decMode, error) { + if !opts.DupMapKey.valid() { + return nil, errors.New("cbor: invalid DupMapKey " + strconv.Itoa(int(opts.DupMapKey))) + } + if !opts.TimeTag.valid() { + return nil, errors.New("cbor: invalid TimeTag " + strconv.Itoa(int(opts.TimeTag))) + } + if !opts.IndefLength.valid() { + return nil, errors.New("cbor: invalid IndefLength " + strconv.Itoa(int(opts.IndefLength))) + } + if !opts.TagsMd.valid() { + return nil, errors.New("cbor: invalid TagsMd " + strconv.Itoa(int(opts.TagsMd))) + } + if !opts.IntDec.valid() { + return nil, errors.New("cbor: invalid IntDec " + strconv.Itoa(int(opts.IntDec))) + } + if !opts.MapKeyByteString.valid() { + return nil, errors.New("cbor: invalid MapKeyByteString " + strconv.Itoa(int(opts.MapKeyByteString))) + } + if opts.MaxNestedLevels == 0 { + opts.MaxNestedLevels = 32 + } else if opts.MaxNestedLevels < 4 || opts.MaxNestedLevels > 65535 { + return nil, errors.New("cbor: invalid MaxNestedLevels " + strconv.Itoa(opts.MaxNestedLevels) + " (range is [4, 65535])") + } + if opts.MaxArrayElements == 0 { + opts.MaxArrayElements = defaultMaxArrayElements + } else if opts.MaxArrayElements < minMaxArrayElements || opts.MaxArrayElements > maxMaxArrayElements { + return nil, errors.New("cbor: invalid MaxArrayElements " + strconv.Itoa(opts.MaxArrayElements) + " (range is [" + strconv.Itoa(minMaxArrayElements) + ", " + strconv.Itoa(maxMaxArrayElements) + "])") + } + if opts.MaxMapPairs == 0 { + opts.MaxMapPairs = defaultMaxMapPairs + } else if opts.MaxMapPairs < minMaxMapPairs || opts.MaxMapPairs > maxMaxMapPairs { + return nil, errors.New("cbor: invalid MaxMapPairs " + strconv.Itoa(opts.MaxMapPairs) + " (range is [" + strconv.Itoa(minMaxMapPairs) + ", " + strconv.Itoa(maxMaxMapPairs) + "])") + } + if !opts.ExtraReturnErrors.valid() { + return nil, errors.New("cbor: invalid ExtraReturnErrors " + strconv.Itoa(int(opts.ExtraReturnErrors))) + } + if opts.DefaultMapType != nil && opts.DefaultMapType.Kind() != reflect.Map { + return nil, fmt.Errorf("cbor: invalid DefaultMapType %s", opts.DefaultMapType) + } + if !opts.UTF8.valid() { + return nil, errors.New("cbor: invalid UTF8 " + strconv.Itoa(int(opts.UTF8))) + } + if !opts.FieldNameMatching.valid() { + return nil, errors.New("cbor: invalid FieldNameMatching " + strconv.Itoa(int(opts.FieldNameMatching))) + } + if !opts.BigIntDec.valid() { + return nil, errors.New("cbor: invalid BigIntDec " + strconv.Itoa(int(opts.BigIntDec))) + } + if opts.DefaultByteStringType != nil && opts.DefaultByteStringType.Kind() != reflect.String && (opts.DefaultByteStringType.Kind() != reflect.Slice || opts.DefaultByteStringType.Elem().Kind() != reflect.Uint8) { + return nil, fmt.Errorf("cbor: invalid DefaultByteStringType: %s is not of kind string or []uint8", opts.DefaultByteStringType) + } + if !opts.ByteStringToString.valid() { + return nil, errors.New("cbor: invalid ByteStringToString " + strconv.Itoa(int(opts.ByteStringToString))) + } + if !opts.FieldNameByteString.valid() { + return nil, errors.New("cbor: invalid FieldNameByteString " + strconv.Itoa(int(opts.FieldNameByteString))) + } + if !opts.UnrecognizedTagToAny.valid() { + return nil, errors.New("cbor: invalid UnrecognizedTagToAnyMode " + strconv.Itoa(int(opts.UnrecognizedTagToAny))) + } + dm := decMode{ + dupMapKey: opts.DupMapKey, + timeTag: opts.TimeTag, + maxNestedLevels: opts.MaxNestedLevels, + maxArrayElements: opts.MaxArrayElements, + maxMapPairs: opts.MaxMapPairs, + indefLength: opts.IndefLength, + tagsMd: opts.TagsMd, + intDec: opts.IntDec, + mapKeyByteString: opts.MapKeyByteString, + extraReturnErrors: opts.ExtraReturnErrors, + defaultMapType: opts.DefaultMapType, + utf8: opts.UTF8, + fieldNameMatching: opts.FieldNameMatching, + bigIntDec: opts.BigIntDec, + defaultByteStringType: opts.DefaultByteStringType, + byteStringToString: opts.ByteStringToString, + fieldNameByteString: opts.FieldNameByteString, + unrecognizedTagToAny: opts.UnrecognizedTagToAny, + } + return &dm, nil +} + +// DecMode is the main interface for CBOR decoding. +type DecMode interface { + // Unmarshal parses the CBOR-encoded data into the value pointed to by v + // using the decoding mode. If v is nil, not a pointer, or a nil pointer, + // Unmarshal returns an error. + // + // See the documentation for Unmarshal for details. + Unmarshal(data []byte, v interface{}) error + + // UnmarshalFirst parses the first CBOR data item into the value pointed to by v + // using the decoding mode. Any remaining bytes are returned in rest. + // + // If v is nil, not a pointer, or a nil pointer, UnmarshalFirst returns an error. + // + // See the documentation for Unmarshal for details. + UnmarshalFirst(data []byte, v interface{}) (rest []byte, err error) + + // Valid checks whether data is a well-formed encoded CBOR data item and + // that it complies with configurable restrictions such as MaxNestedLevels, + // MaxArrayElements, MaxMapPairs, etc. + // + // If there are any remaining bytes after the CBOR data item, + // an ExtraneousDataError is returned. + // + // WARNING: Valid doesn't check if encoded CBOR data item is valid (i.e. validity) + // and RFC 8949 distinctly defines what is "Valid" and what is "Well-formed". + // + // Deprecated: Valid is kept for compatibility and should not be used. + // Use Wellformed instead because it has a more appropriate name. + Valid(data []byte) error + + // Wellformed checks whether data is a well-formed encoded CBOR data item and + // that it complies with configurable restrictions such as MaxNestedLevels, + // MaxArrayElements, MaxMapPairs, etc. + // + // If there are any remaining bytes after the CBOR data item, + // an ExtraneousDataError is returned. + Wellformed(data []byte) error + + // NewDecoder returns a new decoder that reads from r using dm DecMode. + NewDecoder(r io.Reader) *Decoder + + // DecOptions returns user specified options used to create this DecMode. + DecOptions() DecOptions +} + +type decMode struct { + tags tagProvider + dupMapKey DupMapKeyMode + timeTag DecTagMode + maxNestedLevels int + maxArrayElements int + maxMapPairs int + indefLength IndefLengthMode + tagsMd TagsMode + intDec IntDecMode + mapKeyByteString MapKeyByteStringMode + extraReturnErrors ExtraDecErrorCond + defaultMapType reflect.Type + utf8 UTF8Mode + fieldNameMatching FieldNameMatchingMode + bigIntDec BigIntDecMode + defaultByteStringType reflect.Type + byteStringToString ByteStringToStringMode + fieldNameByteString FieldNameByteStringMode + unrecognizedTagToAny UnrecognizedTagToAnyMode +} + +var defaultDecMode, _ = DecOptions{}.decMode() + +// DecOptions returns user specified options used to create this DecMode. +func (dm *decMode) DecOptions() DecOptions { + return DecOptions{ + DupMapKey: dm.dupMapKey, + TimeTag: dm.timeTag, + MaxNestedLevels: dm.maxNestedLevels, + MaxArrayElements: dm.maxArrayElements, + MaxMapPairs: dm.maxMapPairs, + IndefLength: dm.indefLength, + TagsMd: dm.tagsMd, + IntDec: dm.intDec, + MapKeyByteString: dm.mapKeyByteString, + ExtraReturnErrors: dm.extraReturnErrors, + DefaultMapType: dm.defaultMapType, + UTF8: dm.utf8, + FieldNameMatching: dm.fieldNameMatching, + BigIntDec: dm.bigIntDec, + DefaultByteStringType: dm.defaultByteStringType, + ByteStringToString: dm.byteStringToString, + FieldNameByteString: dm.fieldNameByteString, + UnrecognizedTagToAny: dm.unrecognizedTagToAny, + } +} + +// Unmarshal parses the CBOR-encoded data into the value pointed to by v +// using dm decoding mode. If v is nil, not a pointer, or a nil pointer, +// Unmarshal returns an error. +// +// See the documentation for Unmarshal for details. +func (dm *decMode) Unmarshal(data []byte, v interface{}) error { + d := decoder{data: data, dm: dm} + + // Check well-formedness. + off := d.off // Save offset before data validation + err := d.wellformed(false) // don't allow any extra data after valid data item. + d.off = off // Restore offset + if err != nil { + return err + } + + return d.value(v) +} + +// UnmarshalFirst parses the first CBOR data item into the value pointed to by v +// using dm decoding mode. Any remaining bytes are returned in rest. +// +// If v is nil, not a pointer, or a nil pointer, UnmarshalFirst returns an error. +// +// See the documentation for Unmarshal for details. +func (dm *decMode) UnmarshalFirst(data []byte, v interface{}) (rest []byte, err error) { + d := decoder{data: data, dm: dm} + + // check well-formedness. + off := d.off // Save offset before data validation + err = d.wellformed(true) // allow extra data after well-formed data item + d.off = off // Restore offset + + // If it is well-formed, parse the value. This is structured like this to allow + // better test coverage + if err == nil { + err = d.value(v) + } + + // If either wellformed or value returned an error, do not return rest bytes + if err != nil { + return nil, err + } + + // Return the rest of the data slice (which might be len 0) + return d.data[d.off:], nil +} + +// Valid checks whether data is a well-formed encoded CBOR data item and +// that it complies with configurable restrictions such as MaxNestedLevels, +// MaxArrayElements, MaxMapPairs, etc. +// +// If there are any remaining bytes after the CBOR data item, +// an ExtraneousDataError is returned. +// +// WARNING: Valid doesn't check if encoded CBOR data item is valid (i.e. validity) +// and RFC 8949 distinctly defines what is "Valid" and what is "Well-formed". +// +// Deprecated: Valid is kept for compatibility and should not be used. +// Use Wellformed instead because it has a more appropriate name. +func (dm *decMode) Valid(data []byte) error { + return dm.Wellformed(data) +} + +// Wellformed checks whether data is a well-formed encoded CBOR data item and +// that it complies with configurable restrictions such as MaxNestedLevels, +// MaxArrayElements, MaxMapPairs, etc. +// +// If there are any remaining bytes after the CBOR data item, +// an ExtraneousDataError is returned. +func (dm *decMode) Wellformed(data []byte) error { + d := decoder{data: data, dm: dm} + return d.wellformed(false) +} + +// NewDecoder returns a new decoder that reads from r using dm DecMode. +func (dm *decMode) NewDecoder(r io.Reader) *Decoder { + return &Decoder{r: r, d: decoder{dm: dm}} +} + +type decoder struct { + data []byte + off int // next read offset in data + dm *decMode +} + +// value decodes CBOR data item into the value pointed to by v. +// If CBOR data item fails to be decoded into v, +// error is returned and offset is moved to the next CBOR data item. +// Precondition: d.data contains at least one well-formed CBOR data item. +func (d *decoder) value(v interface{}) error { + // v can't be nil, non-pointer, or nil pointer value. + if v == nil { + return &InvalidUnmarshalError{"cbor: Unmarshal(nil)"} + } + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr { + return &InvalidUnmarshalError{"cbor: Unmarshal(non-pointer " + rv.Type().String() + ")"} + } else if rv.IsNil() { + return &InvalidUnmarshalError{"cbor: Unmarshal(nil " + rv.Type().String() + ")"} + } + rv = rv.Elem() + return d.parseToValue(rv, getTypeInfo(rv.Type())) +} + +type cborType uint8 + +const ( + cborTypePositiveInt cborType = 0x00 + cborTypeNegativeInt cborType = 0x20 + cborTypeByteString cborType = 0x40 + cborTypeTextString cborType = 0x60 + cborTypeArray cborType = 0x80 + cborTypeMap cborType = 0xa0 + cborTypeTag cborType = 0xc0 + cborTypePrimitives cborType = 0xe0 +) + +func (t cborType) String() string { + switch t { + case cborTypePositiveInt: + return "positive integer" + case cborTypeNegativeInt: + return "negative integer" + case cborTypeByteString: + return "byte string" + case cborTypeTextString: + return "UTF-8 text string" + case cborTypeArray: + return "array" + case cborTypeMap: + return "map" + case cborTypeTag: + return "tag" + case cborTypePrimitives: + return "primitives" + default: + return "Invalid type " + strconv.Itoa(int(t)) + } +} + +const ( + selfDescribedCBORTagNum = 55799 +) + +// parseToValue decodes CBOR data to value. It assumes data is well-formed, +// and does not perform bounds checking. +func (d *decoder) parseToValue(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo + + // Decode CBOR nil or CBOR undefined to pointer value by setting pointer value to nil. + if d.nextCBORNil() && v.Kind() == reflect.Ptr { + d.skip() + v.Set(reflect.Zero(v.Type())) + return nil + } + + if tInfo.spclType == specialTypeIface { + if !v.IsNil() { + // Use value type + v = v.Elem() + tInfo = getTypeInfo(v.Type()) + } else { + // Create and use registered type if CBOR data is registered tag + if d.dm.tags != nil && d.nextCBORType() == cborTypeTag { + + off := d.off + var tagNums []uint64 + for d.nextCBORType() == cborTypeTag { + _, _, tagNum := d.getHead() + tagNums = append(tagNums, tagNum) + } + d.off = off + + registeredType := d.dm.tags.getTypeFromTagNum(tagNums) + if registeredType != nil { + if registeredType.Implements(tInfo.nonPtrType) || + reflect.PtrTo(registeredType).Implements(tInfo.nonPtrType) { + v.Set(reflect.New(registeredType)) + v = v.Elem() + tInfo = getTypeInfo(registeredType) + } + } + } + } + } + + // Create new value for the pointer v to point to. + // At this point, CBOR value is not nil/undefined if v is a pointer. + for v.Kind() == reflect.Ptr { + if v.IsNil() { + if !v.CanSet() { + d.skip() + return errors.New("cbor: cannot set new value for " + v.Type().String()) + } + v.Set(reflect.New(v.Type().Elem())) + } + v = v.Elem() + } + + // Strip self-described CBOR tag number. + for d.nextCBORType() == cborTypeTag { + off := d.off + _, _, tagNum := d.getHead() + if tagNum != selfDescribedCBORTagNum { + d.off = off + break + } + } + + // Check validity of supported built-in tags. + if d.nextCBORType() == cborTypeTag { + off := d.off + _, _, tagNum := d.getHead() + if err := validBuiltinTag(tagNum, d.data[d.off]); err != nil { + d.skip() + return err + } + d.off = off + } + + if tInfo.spclType != specialTypeNone { + switch tInfo.spclType { + case specialTypeEmptyIface: + iv, err := d.parse(false) // Skipped self-described CBOR tag number already. + if iv != nil { + v.Set(reflect.ValueOf(iv)) + } + return err + case specialTypeTag: + return d.parseToTag(v) + case specialTypeTime: + if d.nextCBORNil() { + // Decoding CBOR null and undefined to time.Time is no-op. + d.skip() + return nil + } + tm, err := d.parseToTime() + if err != nil { + return err + } + v.Set(reflect.ValueOf(tm)) + return nil + case specialTypeUnmarshalerIface: + return d.parseToUnmarshaler(v) + } + } + + // Check registered tag number + if tagItem := d.getRegisteredTagItem(tInfo.nonPtrType); tagItem != nil { + t := d.nextCBORType() + if t != cborTypeTag { + if tagItem.opts.DecTag == DecTagRequired { + d.skip() // Required tag number is absent, skip entire tag + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: tInfo.typ.String(), + errorMsg: "expect CBOR tag value"} + } + } else if err := d.validRegisteredTagNums(tagItem); err != nil { + d.skip() // Skip tag content + return err + } + } + + t := d.nextCBORType() + + switch t { + case cborTypePositiveInt: + _, _, val := d.getHead() + return fillPositiveInt(t, val, v) + + case cborTypeNegativeInt: + _, _, val := d.getHead() + if val > math.MaxInt64 { + // CBOR negative integer overflows int64, use big.Int to store value. + bi := new(big.Int) + bi.SetUint64(val) + bi.Add(bi, big.NewInt(1)) + bi.Neg(bi) + + if tInfo.nonPtrType == typeBigInt { + v.Set(reflect.ValueOf(*bi)) + return nil + } + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: tInfo.nonPtrType.String(), + errorMsg: bi.String() + " overflows Go's int64", + } + } + nValue := int64(-1) ^ int64(val) + return fillNegativeInt(t, nValue, v) + + case cborTypeByteString: + b, copied := d.parseByteString() + return fillByteString(t, b, !copied, v, d.dm.byteStringToString) + + case cborTypeTextString: + b, err := d.parseTextString() + if err != nil { + return err + } + return fillTextString(t, b, v) + + case cborTypePrimitives: + _, ai, val := d.getHead() + switch ai { + case 25: + f := float64(float16.Frombits(uint16(val)).Float32()) + return fillFloat(t, f, v) + case 26: + f := float64(math.Float32frombits(uint32(val))) + return fillFloat(t, f, v) + case 27: + f := math.Float64frombits(val) + return fillFloat(t, f, v) + default: // ai <= 24 + switch ai { + case 20, 21: + return fillBool(t, ai == 21, v) + case 22, 23: + return fillNil(t, v) + default: + return fillPositiveInt(t, val, v) + } + } + + case cborTypeTag: + _, _, tagNum := d.getHead() + switch tagNum { + case 2: + // Bignum (tag 2) can be decoded to uint, int, float, slice, array, or big.Int. + b, copied := d.parseByteString() + bi := new(big.Int).SetBytes(b) + + if tInfo.nonPtrType == typeBigInt { + v.Set(reflect.ValueOf(*bi)) + return nil + } + if tInfo.nonPtrKind == reflect.Slice || tInfo.nonPtrKind == reflect.Array { + return fillByteString(t, b, !copied, v, ByteStringToStringForbidden) + } + if bi.IsUint64() { + return fillPositiveInt(t, bi.Uint64(), v) + } + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: tInfo.nonPtrType.String(), + errorMsg: bi.String() + " overflows " + v.Type().String(), + } + case 3: + // Bignum (tag 3) can be decoded to int, float, slice, array, or big.Int. + b, copied := d.parseByteString() + bi := new(big.Int).SetBytes(b) + bi.Add(bi, big.NewInt(1)) + bi.Neg(bi) + + if tInfo.nonPtrType == typeBigInt { + v.Set(reflect.ValueOf(*bi)) + return nil + } + if tInfo.nonPtrKind == reflect.Slice || tInfo.nonPtrKind == reflect.Array { + return fillByteString(t, b, !copied, v, ByteStringToStringForbidden) + } + if bi.IsInt64() { + return fillNegativeInt(t, bi.Int64(), v) + } + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: tInfo.nonPtrType.String(), + errorMsg: bi.String() + " overflows " + v.Type().String(), + } + } + return d.parseToValue(v, tInfo) + + case cborTypeArray: + if tInfo.nonPtrKind == reflect.Slice { + return d.parseArrayToSlice(v, tInfo) + } else if tInfo.nonPtrKind == reflect.Array { + return d.parseArrayToArray(v, tInfo) + } else if tInfo.nonPtrKind == reflect.Struct { + return d.parseArrayToStruct(v, tInfo) + } + d.skip() + return &UnmarshalTypeError{CBORType: t.String(), GoType: tInfo.nonPtrType.String()} + + case cborTypeMap: + if tInfo.nonPtrKind == reflect.Struct { + return d.parseMapToStruct(v, tInfo) + } else if tInfo.nonPtrKind == reflect.Map { + return d.parseMapToMap(v, tInfo) + } + d.skip() + return &UnmarshalTypeError{CBORType: t.String(), GoType: tInfo.nonPtrType.String()} + } + + return nil +} + +func (d *decoder) parseToTag(v reflect.Value) error { + if d.nextCBORNil() { + // Decoding CBOR null and undefined to cbor.Tag is no-op. + d.skip() + return nil + } + + t := d.nextCBORType() + if t != cborTypeTag { + d.skip() + return &UnmarshalTypeError{CBORType: t.String(), GoType: typeTag.String()} + } + + // Unmarshal tag number + _, _, num := d.getHead() + + // Unmarshal tag content + content, err := d.parse(false) + if err != nil { + return err + } + + v.Set(reflect.ValueOf(Tag{num, content})) + return nil +} + +func (d *decoder) parseToTime() (tm time.Time, err error) { + t := d.nextCBORType() + + // Verify that tag number or absence of tag number is acceptable to specified timeTag. + if t == cborTypeTag { + if d.dm.timeTag == DecTagIgnored { + // Skip tag number + for t == cborTypeTag { + d.getHead() + t = d.nextCBORType() + } + } else { + // Read tag number + _, _, tagNum := d.getHead() + if tagNum != 0 && tagNum != 1 { + d.skip() + err = errors.New("cbor: wrong tag number for time.Time, got " + strconv.Itoa(int(tagNum)) + ", expect 0 or 1") + return + } + } + } else { + if d.dm.timeTag == DecTagRequired { + d.skip() + err = &UnmarshalTypeError{CBORType: t.String(), GoType: typeTime.String(), errorMsg: "expect CBOR tag value"} + return + } + } + + var content interface{} + content, err = d.parse(false) + if err != nil { + return + } + + switch c := content.(type) { + case nil: + return + case uint64: + return time.Unix(int64(c), 0), nil + case int64: + return time.Unix(c, 0), nil + case float64: + if math.IsNaN(c) || math.IsInf(c, 0) { + return + } + f1, f2 := math.Modf(c) + return time.Unix(int64(f1), int64(f2*1e9)), nil + case string: + tm, err = time.Parse(time.RFC3339, c) + if err != nil { + tm = time.Time{} + err = errors.New("cbor: cannot set " + c + " for time.Time: " + err.Error()) + return + } + return + default: + err = &UnmarshalTypeError{CBORType: t.String(), GoType: typeTime.String()} + return + } +} + +// parseToUnmarshaler parses CBOR data to value implementing Unmarshaler interface. +// It assumes data is well-formed, and does not perform bounds checking. +func (d *decoder) parseToUnmarshaler(v reflect.Value) error { + if d.nextCBORNil() && v.Kind() == reflect.Ptr && v.IsNil() { + d.skip() + return nil + } + + if v.Kind() != reflect.Ptr && v.CanAddr() { + v = v.Addr() + } + if u, ok := v.Interface().(Unmarshaler); ok { + start := d.off + d.skip() + return u.UnmarshalCBOR(d.data[start:d.off]) + } + d.skip() + return errors.New("cbor: failed to assert " + v.Type().String() + " as cbor.Unmarshaler") +} + +// parse parses CBOR data and returns value in default Go type. +// It assumes data is well-formed, and does not perform bounds checking. +func (d *decoder) parse(skipSelfDescribedTag bool) (interface{}, error) { //nolint:gocyclo + // Strip self-described CBOR tag number. + if skipSelfDescribedTag { + for d.nextCBORType() == cborTypeTag { + off := d.off + _, _, tagNum := d.getHead() + if tagNum != selfDescribedCBORTagNum { + d.off = off + break + } + } + } + + // Check validity of supported built-in tags. + if d.nextCBORType() == cborTypeTag { + off := d.off + _, _, tagNum := d.getHead() + if err := validBuiltinTag(tagNum, d.data[d.off]); err != nil { + d.skip() + return nil, err + } + d.off = off + } + + t := d.nextCBORType() + switch t { + case cborTypePositiveInt: + _, _, val := d.getHead() + + switch d.dm.intDec { + case IntDecConvertNone: + return val, nil + + case IntDecConvertSigned, IntDecConvertSignedOrFail: + if val > math.MaxInt64 { + return nil, &UnmarshalTypeError{ + CBORType: t.String(), + GoType: reflect.TypeOf(int64(0)).String(), + errorMsg: strconv.FormatUint(val, 10) + " overflows Go's int64", + } + } + + return int64(val), nil + + case IntDecConvertSignedOrBigInt: + if val > math.MaxInt64 { + bi := new(big.Int).SetUint64(val) + if d.dm.bigIntDec == BigIntDecodePointer { + return bi, nil + } + return *bi, nil + } + + return int64(val), nil + + default: + // not reachable + } + + case cborTypeNegativeInt: + _, _, val := d.getHead() + + if val > math.MaxInt64 { + // CBOR negative integer value overflows Go int64, use big.Int instead. + bi := new(big.Int).SetUint64(val) + bi.Add(bi, big.NewInt(1)) + bi.Neg(bi) + + if d.dm.intDec == IntDecConvertSignedOrFail { + return nil, &UnmarshalTypeError{ + CBORType: t.String(), + GoType: reflect.TypeOf(int64(0)).String(), + errorMsg: bi.String() + " overflows Go's int64", + } + } + + if d.dm.bigIntDec == BigIntDecodePointer { + return bi, nil + } + return *bi, nil + } + + nValue := int64(-1) ^ int64(val) + return nValue, nil + + case cborTypeByteString: + switch d.dm.defaultByteStringType { + case nil, typeByteSlice: + b, copied := d.parseByteString() + if copied { + return b, nil + } + clone := make([]byte, len(b)) + copy(clone, b) + return clone, nil + case typeString: + b, _ := d.parseByteString() + return string(b), nil + default: + b, copied := d.parseByteString() + if copied || d.dm.defaultByteStringType.Kind() == reflect.String { + // Avoid an unnecessary copy since the conversion to string must + // copy the underlying bytes. + return reflect.ValueOf(b).Convert(d.dm.defaultByteStringType).Interface(), nil + } + clone := make([]byte, len(b)) + copy(clone, b) + return reflect.ValueOf(clone).Convert(d.dm.defaultByteStringType).Interface(), nil + } + case cborTypeTextString: + b, err := d.parseTextString() + if err != nil { + return nil, err + } + return string(b), nil + case cborTypeTag: + tagOff := d.off + _, _, tagNum := d.getHead() + contentOff := d.off + + switch tagNum { + case 0, 1: + d.off = tagOff + return d.parseToTime() + case 2: + b, _ := d.parseByteString() + bi := new(big.Int).SetBytes(b) + + if d.dm.bigIntDec == BigIntDecodePointer { + return bi, nil + } + return *bi, nil + case 3: + b, _ := d.parseByteString() + bi := new(big.Int).SetBytes(b) + bi.Add(bi, big.NewInt(1)) + bi.Neg(bi) + + if d.dm.bigIntDec == BigIntDecodePointer { + return bi, nil + } + return *bi, nil + } + + if d.dm.tags != nil { + // Parse to specified type if tag number is registered. + tagNums := []uint64{tagNum} + for d.nextCBORType() == cborTypeTag { + _, _, num := d.getHead() + tagNums = append(tagNums, num) + } + registeredType := d.dm.tags.getTypeFromTagNum(tagNums) + if registeredType != nil { + d.off = tagOff + rv := reflect.New(registeredType) + if err := d.parseToValue(rv.Elem(), getTypeInfo(registeredType)); err != nil { + return nil, err + } + return rv.Elem().Interface(), nil + } + } + + // Parse tag content + d.off = contentOff + content, err := d.parse(false) + if err != nil { + return nil, err + } + if d.dm.unrecognizedTagToAny == UnrecognizedTagContentToAny { + return content, nil + } + return Tag{tagNum, content}, nil + case cborTypePrimitives: + _, ai, val := d.getHead() + if ai < 20 || ai == 24 { + return SimpleValue(val), nil + } + switch ai { + case 20, 21: + return (ai == 21), nil + case 22, 23: + return nil, nil + case 25: + f := float64(float16.Frombits(uint16(val)).Float32()) + return f, nil + case 26: + f := float64(math.Float32frombits(uint32(val))) + return f, nil + case 27: + f := math.Float64frombits(val) + return f, nil + } + case cborTypeArray: + return d.parseArray() + case cborTypeMap: + if d.dm.defaultMapType != nil { + m := reflect.New(d.dm.defaultMapType) + err := d.parseToValue(m, getTypeInfo(m.Elem().Type())) + if err != nil { + return nil, err + } + return m.Elem().Interface(), nil + } + return d.parseMap() + } + return nil, nil +} + +// parseByteString parses a CBOR encoded byte string. The returned byte slice +// may be backed directly by the input. The second return value will be true if +// and only if the slice is backed by a copy of the input. Callers are +// responsible for making a copy if necessary. +func (d *decoder) parseByteString() ([]byte, bool) { + _, ai, val := d.getHead() + if ai != 31 { + b := d.data[d.off : d.off+int(val)] + d.off += int(val) + return b, false + } + // Process indefinite length string chunks. + b := []byte{} + for !d.foundBreak() { + _, _, val = d.getHead() + b = append(b, d.data[d.off:d.off+int(val)]...) + d.off += int(val) + } + return b, true +} + +// parseTextString parses CBOR encoded text string. It returns a byte slice +// to prevent creating an extra copy of string. Caller should wrap returned +// byte slice as string when needed. +func (d *decoder) parseTextString() ([]byte, error) { + _, ai, val := d.getHead() + if ai != 31 { + b := d.data[d.off : d.off+int(val)] + d.off += int(val) + if d.dm.utf8 == UTF8RejectInvalid && !utf8.Valid(b) { + return nil, &SemanticError{"cbor: invalid UTF-8 string"} + } + return b, nil + } + // Process indefinite length string chunks. + b := []byte{} + for !d.foundBreak() { + _, _, val = d.getHead() + x := d.data[d.off : d.off+int(val)] + d.off += int(val) + if d.dm.utf8 == UTF8RejectInvalid && !utf8.Valid(x) { + for !d.foundBreak() { + d.skip() // Skip remaining chunk on error + } + return nil, &SemanticError{"cbor: invalid UTF-8 string"} + } + b = append(b, x...) + } + return b, nil +} + +func (d *decoder) parseArray() ([]interface{}, error) { + _, ai, val := d.getHead() + hasSize := (ai != 31) + count := int(val) + if !hasSize { + count = d.numOfItemsUntilBreak() // peek ahead to get array size to preallocate slice for better performance + } + v := make([]interface{}, count) + var e interface{} + var err, lastErr error + for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ { + if e, lastErr = d.parse(true); lastErr != nil { + if err == nil { + err = lastErr + } + continue + } + v[i] = e + } + return v, err +} + +func (d *decoder) parseArrayToSlice(v reflect.Value, tInfo *typeInfo) error { + _, ai, val := d.getHead() + hasSize := (ai != 31) + count := int(val) + if !hasSize { + count = d.numOfItemsUntilBreak() // peek ahead to get array size to preallocate slice for better performance + } + if v.IsNil() || v.Cap() < count || count == 0 { + v.Set(reflect.MakeSlice(tInfo.nonPtrType, count, count)) + } + v.SetLen(count) + var err error + for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ { + if lastErr := d.parseToValue(v.Index(i), tInfo.elemTypeInfo); lastErr != nil { + if err == nil { + err = lastErr + } + } + } + return err +} + +func (d *decoder) parseArrayToArray(v reflect.Value, tInfo *typeInfo) error { + _, ai, val := d.getHead() + hasSize := (ai != 31) + count := int(val) + gi := 0 + vLen := v.Len() + var err error + for ci := 0; (hasSize && ci < count) || (!hasSize && !d.foundBreak()); ci++ { + if gi < vLen { + // Read CBOR array element and set array element + if lastErr := d.parseToValue(v.Index(gi), tInfo.elemTypeInfo); lastErr != nil { + if err == nil { + err = lastErr + } + } + gi++ + } else { + d.skip() // Skip remaining CBOR array element + } + } + // Set remaining Go array elements to zero values. + if gi < vLen { + zeroV := reflect.Zero(tInfo.elemTypeInfo.typ) + for ; gi < vLen; gi++ { + v.Index(gi).Set(zeroV) + } + } + return err +} + +func (d *decoder) parseMap() (interface{}, error) { + _, ai, val := d.getHead() + hasSize := (ai != 31) + count := int(val) + m := make(map[interface{}]interface{}) + var k, e interface{} + var err, lastErr error + keyCount := 0 + for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ { + // Parse CBOR map key. + if k, lastErr = d.parse(true); lastErr != nil { + if err == nil { + err = lastErr + } + d.skip() + continue + } + + // Detect if CBOR map key can be used as Go map key. + rv := reflect.ValueOf(k) + if !isHashableValue(rv) { + var converted bool + if d.dm.mapKeyByteString == MapKeyByteStringAllowed { + k, converted = convertByteSliceToByteString(k) + } + if !converted { + if err == nil { + err = &InvalidMapKeyTypeError{rv.Type().String()} + } + d.skip() + continue + } + } + + // Parse CBOR map value. + if e, lastErr = d.parse(true); lastErr != nil { + if err == nil { + err = lastErr + } + continue + } + + // Add key-value pair to Go map. + m[k] = e + + // Detect duplicate map key. + if d.dm.dupMapKey == DupMapKeyEnforcedAPF { + newKeyCount := len(m) + if newKeyCount == keyCount { + m[k] = nil + err = &DupMapKeyError{k, i} + i++ + // skip the rest of the map + for ; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ { + d.skip() // Skip map key + d.skip() // Skip map value + } + return m, err + } + keyCount = newKeyCount + } + } + return m, err +} + +func (d *decoder) parseMapToMap(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo + _, ai, val := d.getHead() + hasSize := (ai != 31) + count := int(val) + if v.IsNil() { + mapsize := count + if !hasSize { + mapsize = 0 + } + v.Set(reflect.MakeMapWithSize(tInfo.nonPtrType, mapsize)) + } + keyType, eleType := tInfo.keyTypeInfo.typ, tInfo.elemTypeInfo.typ + reuseKey, reuseEle := isImmutableKind(tInfo.keyTypeInfo.kind), isImmutableKind(tInfo.elemTypeInfo.kind) + var keyValue, eleValue, zeroKeyValue, zeroEleValue reflect.Value + keyIsInterfaceType := keyType == typeIntf // If key type is interface{}, need to check if key value is hashable. + var err, lastErr error + keyCount := v.Len() + var existingKeys map[interface{}]bool // Store existing map keys, used for detecting duplicate map key. + if d.dm.dupMapKey == DupMapKeyEnforcedAPF { + existingKeys = make(map[interface{}]bool, keyCount) + if keyCount > 0 { + vKeys := v.MapKeys() + for i := 0; i < len(vKeys); i++ { + existingKeys[vKeys[i].Interface()] = true + } + } + } + for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ { + // Parse CBOR map key. + if !keyValue.IsValid() { + keyValue = reflect.New(keyType).Elem() + } else if !reuseKey { + if !zeroKeyValue.IsValid() { + zeroKeyValue = reflect.Zero(keyType) + } + keyValue.Set(zeroKeyValue) + } + if lastErr = d.parseToValue(keyValue, tInfo.keyTypeInfo); lastErr != nil { + if err == nil { + err = lastErr + } + d.skip() + continue + } + + // Detect if CBOR map key can be used as Go map key. + if keyIsInterfaceType && keyValue.Elem().IsValid() { + if !isHashableValue(keyValue.Elem()) { + var converted bool + if d.dm.mapKeyByteString == MapKeyByteStringAllowed { + var k interface{} + k, converted = convertByteSliceToByteString(keyValue.Elem().Interface()) + if converted { + keyValue.Set(reflect.ValueOf(k)) + } + } + if !converted { + if err == nil { + err = &InvalidMapKeyTypeError{keyValue.Elem().Type().String()} + } + d.skip() + continue + } + } + } + + // Parse CBOR map value. + if !eleValue.IsValid() { + eleValue = reflect.New(eleType).Elem() + } else if !reuseEle { + if !zeroEleValue.IsValid() { + zeroEleValue = reflect.Zero(eleType) + } + eleValue.Set(zeroEleValue) + } + if lastErr := d.parseToValue(eleValue, tInfo.elemTypeInfo); lastErr != nil { + if err == nil { + err = lastErr + } + continue + } + + // Add key-value pair to Go map. + v.SetMapIndex(keyValue, eleValue) + + // Detect duplicate map key. + if d.dm.dupMapKey == DupMapKeyEnforcedAPF { + newKeyCount := v.Len() + if newKeyCount == keyCount { + kvi := keyValue.Interface() + if !existingKeys[kvi] { + v.SetMapIndex(keyValue, reflect.New(eleType).Elem()) + err = &DupMapKeyError{kvi, i} + i++ + // skip the rest of the map + for ; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ { + d.skip() // skip map key + d.skip() // skip map value + } + return err + } + delete(existingKeys, kvi) + } + keyCount = newKeyCount + } + } + return err +} + +func (d *decoder) parseArrayToStruct(v reflect.Value, tInfo *typeInfo) error { + structType := getDecodingStructType(tInfo.nonPtrType) + if structType.err != nil { + return structType.err + } + + if !structType.toArray { + t := d.nextCBORType() + d.skip() + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: tInfo.nonPtrType.String(), + errorMsg: "cannot decode CBOR array to struct without toarray option", + } + } + + start := d.off + t, ai, val := d.getHead() + hasSize := (ai != 31) + count := int(val) + if !hasSize { + count = d.numOfItemsUntilBreak() // peek ahead to get array size + } + if count != len(structType.fields) { + d.off = start + d.skip() + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: tInfo.typ.String(), + errorMsg: "cannot decode CBOR array to struct with different number of elements", + } + } + var err, lastErr error + for i := 0; (hasSize && i < count) || (!hasSize && !d.foundBreak()); i++ { + f := structType.fields[i] + + // Get field value by index + var fv reflect.Value + if len(f.idx) == 1 { + fv = v.Field(f.idx[0]) + } else { + fv, lastErr = getFieldValue(v, f.idx, func(v reflect.Value) (reflect.Value, error) { + // Return a new value for embedded field null pointer to point to, or return error. + if !v.CanSet() { + return reflect.Value{}, errors.New("cbor: cannot set embedded pointer to unexported struct: " + v.Type().String()) + } + v.Set(reflect.New(v.Type().Elem())) + return v, nil + }) + if lastErr != nil && err == nil { + err = lastErr + } + if !fv.IsValid() { + d.skip() + continue + } + } + + if lastErr = d.parseToValue(fv, f.typInfo); lastErr != nil { + if err == nil { + if typeError, ok := lastErr.(*UnmarshalTypeError); ok { + typeError.StructFieldName = tInfo.typ.String() + "." + f.name + err = typeError + } else { + err = lastErr + } + } + } + } + return err +} + +// parseMapToStruct needs to be fast so gocyclo can be ignored for now. +func (d *decoder) parseMapToStruct(v reflect.Value, tInfo *typeInfo) error { //nolint:gocyclo + structType := getDecodingStructType(tInfo.nonPtrType) + if structType.err != nil { + return structType.err + } + + if structType.toArray { + t := d.nextCBORType() + d.skip() + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: tInfo.nonPtrType.String(), + errorMsg: "cannot decode CBOR map to struct with toarray option", + } + } + + var err, lastErr error + + // Get CBOR map size + _, ai, val := d.getHead() + hasSize := (ai != 31) + count := int(val) + + // Keeps track of matched struct fields + foundFldIdx := make([]bool, len(structType.fields)) + + // Keeps track of CBOR map keys to detect duplicate map key + keyCount := 0 + var mapKeys map[interface{}]struct{} + if d.dm.dupMapKey == DupMapKeyEnforcedAPF { + mapKeys = make(map[interface{}]struct{}, len(structType.fields)) + } + + errOnUnknownField := (d.dm.extraReturnErrors & ExtraDecErrorUnknownField) > 0 + + for j := 0; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ { + var f *field + var k interface{} // Used by duplicate map key detection + + t := d.nextCBORType() + if t == cborTypeTextString || (t == cborTypeByteString && d.dm.fieldNameByteString == FieldNameByteStringAllowed) { + var keyBytes []byte + if t == cborTypeTextString { + keyBytes, lastErr = d.parseTextString() + if lastErr != nil { + if err == nil { + err = lastErr + } + d.skip() // skip value + continue + } + } else { // cborTypeByteString + keyBytes, _ = d.parseByteString() + } + + keyLen := len(keyBytes) + // Find field with exact match + for i := 0; i < len(structType.fields); i++ { + fld := structType.fields[i] + if !foundFldIdx[i] && len(fld.name) == keyLen && fld.name == string(keyBytes) { + f = fld + foundFldIdx[i] = true + break + } + } + // Find field with case-insensitive match + if f == nil && d.dm.fieldNameMatching == FieldNameMatchingPreferCaseSensitive { + keyString := string(keyBytes) + for i := 0; i < len(structType.fields); i++ { + fld := structType.fields[i] + if !foundFldIdx[i] && len(fld.name) == keyLen && strings.EqualFold(fld.name, keyString) { + f = fld + foundFldIdx[i] = true + break + } + } + } + + if d.dm.dupMapKey == DupMapKeyEnforcedAPF { + k = string(keyBytes) + } + } else if t <= cborTypeNegativeInt { // uint/int + var nameAsInt int64 + + if t == cborTypePositiveInt { + _, _, val := d.getHead() + nameAsInt = int64(val) + } else { + _, _, val := d.getHead() + if val > math.MaxInt64 { + if err == nil { + err = &UnmarshalTypeError{ + CBORType: t.String(), + GoType: reflect.TypeOf(int64(0)).String(), + errorMsg: "-1-" + strconv.FormatUint(val, 10) + " overflows Go's int64", + } + } + d.skip() // skip value + continue + } + nameAsInt = int64(-1) ^ int64(val) + } + + // Find field + for i := 0; i < len(structType.fields); i++ { + fld := structType.fields[i] + if !foundFldIdx[i] && fld.keyAsInt && fld.nameAsInt == nameAsInt { + f = fld + foundFldIdx[i] = true + break + } + } + + if d.dm.dupMapKey == DupMapKeyEnforcedAPF { + k = nameAsInt + } + } else { + if err == nil { + err = &UnmarshalTypeError{ + CBORType: t.String(), + GoType: reflect.TypeOf("").String(), + errorMsg: "map key is of type " + t.String() + " and cannot be used to match struct field name", + } + } + if d.dm.dupMapKey == DupMapKeyEnforcedAPF { + // parse key + k, lastErr = d.parse(true) + if lastErr != nil { + d.skip() // skip value + continue + } + // Detect if CBOR map key can be used as Go map key. + if !isHashableValue(reflect.ValueOf(k)) { + d.skip() // skip value + continue + } + } else { + d.skip() // skip key + } + } + + if d.dm.dupMapKey == DupMapKeyEnforcedAPF { + mapKeys[k] = struct{}{} + newKeyCount := len(mapKeys) + if newKeyCount == keyCount { + err = &DupMapKeyError{k, j} + d.skip() // skip value + j++ + // skip the rest of the map + for ; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ { + d.skip() + d.skip() + } + return err + } + keyCount = newKeyCount + } + + if f == nil { + if errOnUnknownField { + err = &UnknownFieldError{j} + d.skip() // Skip value + j++ + // skip the rest of the map + for ; (hasSize && j < count) || (!hasSize && !d.foundBreak()); j++ { + d.skip() + d.skip() + } + return err + } + d.skip() // Skip value + continue + } + + // Get field value by index + var fv reflect.Value + if len(f.idx) == 1 { + fv = v.Field(f.idx[0]) + } else { + fv, lastErr = getFieldValue(v, f.idx, func(v reflect.Value) (reflect.Value, error) { + // Return a new value for embedded field null pointer to point to, or return error. + if !v.CanSet() { + return reflect.Value{}, errors.New("cbor: cannot set embedded pointer to unexported struct: " + v.Type().String()) + } + v.Set(reflect.New(v.Type().Elem())) + return v, nil + }) + if lastErr != nil && err == nil { + err = lastErr + } + if !fv.IsValid() { + d.skip() + continue + } + } + + if lastErr = d.parseToValue(fv, f.typInfo); lastErr != nil { + if err == nil { + if typeError, ok := lastErr.(*UnmarshalTypeError); ok { + typeError.StructFieldName = tInfo.nonPtrType.String() + "." + f.name + err = typeError + } else { + err = lastErr + } + } + } + } + return err +} + +// validRegisteredTagNums verifies that tag numbers match registered tag numbers of type t. +// validRegisteredTagNums assumes next CBOR data type is tag. It scans all tag numbers, and stops at tag content. +func (d *decoder) validRegisteredTagNums(registeredTag *tagItem) error { + // Scan until next cbor data is tag content. + tagNums := make([]uint64, 0, 1) + for d.nextCBORType() == cborTypeTag { + _, _, val := d.getHead() + tagNums = append(tagNums, val) + } + + if !registeredTag.equalTagNum(tagNums) { + return &WrongTagError{registeredTag.contentType, registeredTag.num, tagNums} + } + return nil +} + +func (d *decoder) getRegisteredTagItem(vt reflect.Type) *tagItem { + if d.dm.tags != nil { + return d.dm.tags.getTagItemFromType(vt) + } + return nil +} + +// skip moves data offset to the next item. skip assumes data is well-formed, +// and does not perform bounds checking. +func (d *decoder) skip() { + t, ai, val := d.getHead() + + if ai == 31 { + switch t { + case cborTypeByteString, cborTypeTextString, cborTypeArray, cborTypeMap: + for { + if d.data[d.off] == 0xff { + d.off++ + return + } + d.skip() + } + } + } + + switch t { + case cborTypeByteString, cborTypeTextString: + d.off += int(val) + case cborTypeArray: + for i := 0; i < int(val); i++ { + d.skip() + } + case cborTypeMap: + for i := 0; i < int(val)*2; i++ { + d.skip() + } + case cborTypeTag: + d.skip() + } +} + +// getHead assumes data is well-formed, and does not perform bounds checking. +func (d *decoder) getHead() (t cborType, ai byte, val uint64) { + t = cborType(d.data[d.off] & 0xe0) + ai = d.data[d.off] & 0x1f + val = uint64(ai) + d.off++ + + if ai < 24 { + return + } + if ai == 24 { + val = uint64(d.data[d.off]) + d.off++ + return + } + if ai == 25 { + val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+2])) + d.off += 2 + return + } + if ai == 26 { + val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+4])) + d.off += 4 + return + } + if ai == 27 { + val = binary.BigEndian.Uint64(d.data[d.off : d.off+8]) + d.off += 8 + return + } + return +} + +func (d *decoder) numOfItemsUntilBreak() int { + savedOff := d.off + i := 0 + for !d.foundBreak() { + d.skip() + i++ + } + d.off = savedOff + return i +} + +// foundBreak assumes data is well-formed, and does not perform bounds checking. +func (d *decoder) foundBreak() bool { + if d.data[d.off] == 0xff { + d.off++ + return true + } + return false +} + +func (d *decoder) reset(data []byte) { + d.data = data + d.off = 0 +} + +func (d *decoder) nextCBORType() cborType { + return cborType(d.data[d.off] & 0xe0) +} + +func (d *decoder) nextCBORNil() bool { + return d.data[d.off] == 0xf6 || d.data[d.off] == 0xf7 +} + +var ( + typeIntf = reflect.TypeOf([]interface{}(nil)).Elem() + typeTime = reflect.TypeOf(time.Time{}) + typeBigInt = reflect.TypeOf(big.Int{}) + typeUnmarshaler = reflect.TypeOf((*Unmarshaler)(nil)).Elem() + typeBinaryUnmarshaler = reflect.TypeOf((*encoding.BinaryUnmarshaler)(nil)).Elem() + typeString = reflect.TypeOf("") + typeByteSlice = reflect.TypeOf([]byte(nil)) +) + +func fillNil(_ cborType, v reflect.Value) error { + switch v.Kind() { + case reflect.Slice, reflect.Map, reflect.Interface, reflect.Ptr: + v.Set(reflect.Zero(v.Type())) + return nil + } + return nil +} + +func fillPositiveInt(t cborType, val uint64, v reflect.Value) error { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if val > math.MaxInt64 { + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: v.Type().String(), + errorMsg: strconv.FormatUint(val, 10) + " overflows " + v.Type().String(), + } + } + if v.OverflowInt(int64(val)) { + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: v.Type().String(), + errorMsg: strconv.FormatUint(val, 10) + " overflows " + v.Type().String(), + } + } + v.SetInt(int64(val)) + return nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if v.OverflowUint(val) { + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: v.Type().String(), + errorMsg: strconv.FormatUint(val, 10) + " overflows " + v.Type().String(), + } + } + v.SetUint(val) + return nil + case reflect.Float32, reflect.Float64: + f := float64(val) + v.SetFloat(f) + return nil + } + if v.Type() == typeBigInt { + i := new(big.Int).SetUint64(val) + v.Set(reflect.ValueOf(*i)) + return nil + } + return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()} +} + +func fillNegativeInt(t cborType, val int64, v reflect.Value) error { + switch v.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if v.OverflowInt(val) { + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: v.Type().String(), + errorMsg: strconv.FormatInt(val, 10) + " overflows " + v.Type().String(), + } + } + v.SetInt(val) + return nil + case reflect.Float32, reflect.Float64: + f := float64(val) + v.SetFloat(f) + return nil + } + if v.Type() == typeBigInt { + i := new(big.Int).SetInt64(val) + v.Set(reflect.ValueOf(*i)) + return nil + } + return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()} +} + +func fillBool(t cborType, val bool, v reflect.Value) error { + if v.Kind() == reflect.Bool { + v.SetBool(val) + return nil + } + return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()} +} + +func fillFloat(t cborType, val float64, v reflect.Value) error { + switch v.Kind() { + case reflect.Float32, reflect.Float64: + if v.OverflowFloat(val) { + return &UnmarshalTypeError{ + CBORType: t.String(), + GoType: v.Type().String(), + errorMsg: strconv.FormatFloat(val, 'E', -1, 64) + " overflows " + v.Type().String(), + } + } + v.SetFloat(val) + return nil + } + return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()} +} + +func fillByteString(t cborType, val []byte, shared bool, v reflect.Value, bsts ByteStringToStringMode) error { + if reflect.PtrTo(v.Type()).Implements(typeBinaryUnmarshaler) { + if v.CanAddr() { + v = v.Addr() + if u, ok := v.Interface().(encoding.BinaryUnmarshaler); ok { + // The contract of BinaryUnmarshaler forbids + // retaining the input bytes, so no copying is + // required even if val is shared. + return u.UnmarshalBinary(val) + } + } + return errors.New("cbor: cannot set new value for " + v.Type().String()) + } + if bsts == ByteStringToStringAllowed && v.Kind() == reflect.String { + v.SetString(string(val)) + return nil + } + if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 { + src := val + if shared { + // SetBytes shares the underlying bytes of the source slice. + src = make([]byte, len(val)) + copy(src, val) + } + v.SetBytes(src) + return nil + } + if v.Kind() == reflect.Array && v.Type().Elem().Kind() == reflect.Uint8 { + vLen := v.Len() + i := 0 + for ; i < vLen && i < len(val); i++ { + v.Index(i).SetUint(uint64(val[i])) + } + // Set remaining Go array elements to zero values. + if i < vLen { + zeroV := reflect.Zero(reflect.TypeOf(byte(0))) + for ; i < vLen; i++ { + v.Index(i).Set(zeroV) + } + } + return nil + } + return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()} +} + +func fillTextString(t cborType, val []byte, v reflect.Value) error { + if v.Kind() == reflect.String { + v.SetString(string(val)) + return nil + } + return &UnmarshalTypeError{CBORType: t.String(), GoType: v.Type().String()} +} + +func isImmutableKind(k reflect.Kind) bool { + switch k { + case reflect.Bool, + 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: + return true + default: + return false + } +} + +func isHashableValue(rv reflect.Value) bool { + switch rv.Kind() { + case reflect.Slice, reflect.Map, reflect.Func: + return false + case reflect.Struct: + switch rv.Type() { + case typeTag: + tag := rv.Interface().(Tag) + return isHashableValue(reflect.ValueOf(tag.Content)) + case typeBigInt: + return false + } + } + return true +} + +// convertByteSliceToByteString converts []byte to ByteString if +// - v is []byte type, or +// - v is Tag type and tag content type is []byte +// This function also handles nested tags. +// CBOR data is already verified to be well-formed before this function is used, +// so the recursion won't exceed max nested levels. +func convertByteSliceToByteString(v interface{}) (interface{}, bool) { + switch v := v.(type) { + case []byte: + return ByteString(v), true + case Tag: + content, converted := convertByteSliceToByteString(v.Content) + if converted { + return Tag{Number: v.Number, Content: content}, true + } + } + return v, false +} + +// validBuiltinTag checks that supported built-in tag numbers are followed by expected content types. +func validBuiltinTag(tagNum uint64, contentHead byte) error { + t := cborType(contentHead & 0xe0) + switch tagNum { + case 0: + // Tag content (date/time text string in RFC 3339 format) must be string type. + if t != cborTypeTextString { + return errors.New("cbor: tag number 0 must be followed by text string, got " + t.String()) + } + return nil + case 1: + // Tag content (epoch date/time) must be uint, int, or float type. + if t != cborTypePositiveInt && t != cborTypeNegativeInt && (contentHead < 0xf9 || contentHead > 0xfb) { + return errors.New("cbor: tag number 1 must be followed by integer or floating-point number, got " + t.String()) + } + return nil + case 2, 3: + // Tag content (bignum) must be byte type. + if t != cborTypeByteString { + return errors.New("cbor: tag number 2 or 3 must be followed by byte string, got " + t.String()) + } + return nil + } + return nil +} diff --git a/vendor/github.com/fxamacker/cbor/v2/diagnose.go b/vendor/github.com/fxamacker/cbor/v2/diagnose.go new file mode 100644 index 00000000..43e6a14c --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/diagnose.go @@ -0,0 +1,741 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +package cbor + +import ( + "bytes" + "encoding/base32" + "encoding/base64" + "encoding/hex" + "errors" + "io" + "math" + "math/big" + "strconv" + "unicode/utf16" + "unicode/utf8" + + "github.com/x448/float16" +) + +// DiagMode is the main interface for CBOR diagnostic notation. +type DiagMode interface { + // Diagnose returns extended diagnostic notation (EDN) of CBOR data items using this DiagMode. + Diagnose([]byte) (string, error) + + // DiagnoseFirst returns extended diagnostic notation (EDN) of the first CBOR data item using the DiagMode. Any remaining bytes are returned in rest. + DiagnoseFirst([]byte) (string, []byte, error) + + // DiagOptions returns user specified options used to create this DiagMode. + DiagOptions() DiagOptions +} + +// ByteStringEncoding specifies the base encoding that byte strings are notated. +type ByteStringEncoding uint8 + +const ( + // ByteStringBase16Encoding encodes byte strings in base16, without padding. + ByteStringBase16Encoding ByteStringEncoding = iota + + // ByteStringBase32Encoding encodes byte strings in base32, without padding. + ByteStringBase32Encoding + + // ByteStringBase32HexEncoding encodes byte strings in base32hex, without padding. + ByteStringBase32HexEncoding + + // ByteStringBase64Encoding encodes byte strings in base64url, without padding. + ByteStringBase64Encoding + + maxByteStringEncoding +) + +func (bse ByteStringEncoding) valid() error { + if bse >= maxByteStringEncoding { + return errors.New("cbor: invalid ByteStringEncoding " + strconv.Itoa(int(bse))) + } + return nil +} + +// DiagOptions specifies Diag options. +type DiagOptions struct { + // ByteStringEncoding specifies the base encoding that byte strings are notated. + // Default is ByteStringBase16Encoding. + ByteStringEncoding ByteStringEncoding + + // ByteStringHexWhitespace specifies notating with whitespace in byte string + // when ByteStringEncoding is ByteStringBase16Encoding. + ByteStringHexWhitespace bool + + // ByteStringText specifies notating with text in byte string + // if it is a valid UTF-8 text. + ByteStringText bool + + // ByteStringEmbeddedCBOR specifies notating embedded CBOR in byte string + // if it is a valid CBOR bytes. + ByteStringEmbeddedCBOR bool + + // CBORSequence specifies notating CBOR sequences. + // otherwise, it returns an error if there are more bytes after the first CBOR. + CBORSequence bool + + // FloatPrecisionIndicator specifies appending a suffix to indicate float precision. + // Refer to https://www.rfc-editor.org/rfc/rfc8949.html#name-encoding-indicators. + FloatPrecisionIndicator bool + + // MaxNestedLevels specifies the max nested levels allowed for any combination of CBOR array, maps, and tags. + // Default is 32 levels and it can be set to [4, 65535]. Note that higher maximum levels of nesting can + // require larger amounts of stack to deserialize. Don't increase this higher than you require. + MaxNestedLevels int + + // MaxArrayElements specifies the max number of elements for CBOR arrays. + // Default is 128*1024=131072 and it can be set to [16, 2147483647] + MaxArrayElements int + + // MaxMapPairs specifies the max number of key-value pairs for CBOR maps. + // Default is 128*1024=131072 and it can be set to [16, 2147483647] + MaxMapPairs int +} + +// DiagMode returns a DiagMode with immutable options. +func (opts DiagOptions) DiagMode() (DiagMode, error) { + return opts.diagMode() +} + +func (opts DiagOptions) diagMode() (*diagMode, error) { + if err := opts.ByteStringEncoding.valid(); err != nil { + return nil, err + } + + decMode, err := DecOptions{ + MaxNestedLevels: opts.MaxNestedLevels, + MaxArrayElements: opts.MaxArrayElements, + MaxMapPairs: opts.MaxMapPairs, + }.decMode() + if err != nil { + return nil, err + } + + return &diagMode{ + byteStringEncoding: opts.ByteStringEncoding, + byteStringHexWhitespace: opts.ByteStringHexWhitespace, + byteStringText: opts.ByteStringText, + byteStringEmbeddedCBOR: opts.ByteStringEmbeddedCBOR, + cborSequence: opts.CBORSequence, + floatPrecisionIndicator: opts.FloatPrecisionIndicator, + decMode: decMode, + }, nil +} + +type diagMode struct { + byteStringEncoding ByteStringEncoding + byteStringHexWhitespace bool + byteStringText bool + byteStringEmbeddedCBOR bool + cborSequence bool + floatPrecisionIndicator bool + decMode *decMode +} + +// DiagOptions returns user specified options used to create this DiagMode. +func (dm *diagMode) DiagOptions() DiagOptions { + return DiagOptions{ + ByteStringEncoding: dm.byteStringEncoding, + ByteStringHexWhitespace: dm.byteStringHexWhitespace, + ByteStringText: dm.byteStringText, + ByteStringEmbeddedCBOR: dm.byteStringEmbeddedCBOR, + CBORSequence: dm.cborSequence, + FloatPrecisionIndicator: dm.floatPrecisionIndicator, + MaxNestedLevels: dm.decMode.maxNestedLevels, + MaxArrayElements: dm.decMode.maxArrayElements, + MaxMapPairs: dm.decMode.maxMapPairs, + } +} + +// Diagnose returns extended diagnostic notation (EDN) of CBOR data items using the DiagMode. +func (dm *diagMode) Diagnose(data []byte) (string, error) { + return newDiagnose(data, dm.decMode, dm).diag(dm.cborSequence) +} + +// DiagnoseFirst returns extended diagnostic notation (EDN) of the first CBOR data item using the DiagMode. Any remaining bytes are returned in rest. +func (dm *diagMode) DiagnoseFirst(data []byte) (string, []byte, error) { + return newDiagnose(data, dm.decMode, dm).diagFirst() +} + +var defaultDiagMode, _ = DiagOptions{}.diagMode() + +// Diagnose returns extended diagnostic notation (EDN) of CBOR data items +// using the default diagnostic mode. +// +// Refer to https://www.rfc-editor.org/rfc/rfc8949.html#name-diagnostic-notation. +func Diagnose(data []byte) (string, error) { + return defaultDiagMode.Diagnose(data) +} + +// Diagnose returns extended diagnostic notation (EDN) of the first CBOR data item using the DiagMode. Any remaining bytes are returned in rest. +func DiagnoseFirst(data []byte) (string, []byte, error) { + return defaultDiagMode.DiagnoseFirst(data) +} + +type diagnose struct { + dm *diagMode + d *decoder + w *bytes.Buffer +} + +func newDiagnose(data []byte, decm *decMode, diagm *diagMode) *diagnose { + return &diagnose{ + dm: diagm, + d: &decoder{data: data, dm: decm}, + w: &bytes.Buffer{}, + } +} + +func (di *diagnose) diag(cborSequence bool) (string, error) { + // CBOR Sequence + firstItem := true + for { + switch err := di.wellformed(cborSequence); err { + case nil: + if !firstItem { + if err = di.writeString(", "); err != nil { + return di.w.String(), err + } + } + firstItem = false + if err = di.item(); err != nil { + return di.w.String(), err + } + + case io.EOF: + if firstItem { + return di.w.String(), err + } + return di.w.String(), nil + + default: + return di.w.String(), err + } + } +} + +func (di *diagnose) diagFirst() (string, []byte, error) { + err := di.wellformed(true) + if err == nil { + err = di.item() + } + + if err == nil { + // Return EDN and the rest of the data slice (which might be len 0) + return di.w.String(), di.d.data[di.d.off:], nil + } + + return di.w.String(), nil, err +} + +func (di *diagnose) wellformed(allowExtraData bool) error { + off := di.d.off + err := di.d.wellformed(allowExtraData) + di.d.off = off + return err +} + +func (di *diagnose) item() error { //nolint:gocyclo + initialByte := di.d.data[di.d.off] + switch initialByte { + case 0x5f, 0x7f: // indefinite-length byte/text string + di.d.off++ + if di.d.data[di.d.off] == 0xff { + di.d.off++ + switch initialByte { + case 0x5f: + // indefinite-length bytes with no chunks. + return di.writeString(`''_`) + case 0x7f: + // indefinite-length text with no chunks. + return di.writeString(`""_`) + } + } + + if err := di.writeString("(_ "); err != nil { + return err + } + + i := 0 + for !di.d.foundBreak() { + if i > 0 { + if err := di.writeString(", "); err != nil { + return err + } + } + + i++ + // wellformedIndefiniteString() already checked that the next item is a byte/text string. + if err := di.item(); err != nil { + return err + } + } + + return di.writeByte(')') + + case 0x9f: // indefinite-length array + di.d.off++ + if err := di.writeString("[_ "); err != nil { + return err + } + + i := 0 + for !di.d.foundBreak() { + if i > 0 { + if err := di.writeString(", "); err != nil { + return err + } + } + + i++ + if err := di.item(); err != nil { + return err + } + } + + return di.writeByte(']') + + case 0xbf: // indefinite-length map + di.d.off++ + if err := di.writeString("{_ "); err != nil { + return err + } + + i := 0 + for !di.d.foundBreak() { + if i > 0 { + if err := di.writeString(", "); err != nil { + return err + } + } + + i++ + // key + if err := di.item(); err != nil { + return err + } + + if err := di.writeString(": "); err != nil { + return err + } + + // value + if err := di.item(); err != nil { + return err + } + } + + return di.writeByte('}') + } + + t := di.d.nextCBORType() + switch t { + case cborTypePositiveInt: + _, _, val := di.d.getHead() + return di.writeString(strconv.FormatUint(val, 10)) + + case cborTypeNegativeInt: + _, _, val := di.d.getHead() + if val > math.MaxInt64 { + // CBOR negative integer overflows int64, use big.Int to store value. + bi := new(big.Int) + bi.SetUint64(val) + bi.Add(bi, big.NewInt(1)) + bi.Neg(bi) + return di.writeString(bi.String()) + } + + nValue := int64(-1) ^ int64(val) + return di.writeString(strconv.FormatInt(nValue, 10)) + + case cborTypeByteString: + b, _ := di.d.parseByteString() + return di.encodeByteString(b) + + case cborTypeTextString: + b, err := di.d.parseTextString() + if err != nil { + return err + } + return di.encodeTextString(string(b), '"') + + case cborTypeArray: + _, _, val := di.d.getHead() + count := int(val) + if err := di.writeByte('['); err != nil { + return err + } + + for i := 0; i < count; i++ { + if i > 0 { + if err := di.writeString(", "); err != nil { + return err + } + } + if err := di.item(); err != nil { + return err + } + } + return di.writeByte(']') + + case cborTypeMap: + _, _, val := di.d.getHead() + count := int(val) + if err := di.writeByte('{'); err != nil { + return err + } + + for i := 0; i < count; i++ { + if i > 0 { + if err := di.writeString(", "); err != nil { + return err + } + } + // key + if err := di.item(); err != nil { + return err + } + if err := di.writeString(": "); err != nil { + return err + } + // value + if err := di.item(); err != nil { + return err + } + } + return di.writeByte('}') + + case cborTypeTag: + _, _, tagNum := di.d.getHead() + switch tagNum { + case 2: + if nt := di.d.nextCBORType(); nt != cborTypeByteString { + return errors.New("cbor: tag number 2 must be followed by byte string, got " + nt.String()) + } + + b, _ := di.d.parseByteString() + bi := new(big.Int).SetBytes(b) + return di.writeString(bi.String()) + + case 3: + if nt := di.d.nextCBORType(); nt != cborTypeByteString { + return errors.New("cbor: tag number 3 must be followed by byte string, got " + nt.String()) + } + + b, _ := di.d.parseByteString() + bi := new(big.Int).SetBytes(b) + bi.Add(bi, big.NewInt(1)) + bi.Neg(bi) + return di.writeString(bi.String()) + + default: + if err := di.writeString(strconv.FormatUint(tagNum, 10)); err != nil { + return err + } + if err := di.writeByte('('); err != nil { + return err + } + if err := di.item(); err != nil { + return err + } + return di.writeByte(')') + } + + case cborTypePrimitives: + _, ai, val := di.d.getHead() + switch ai { + case 20: + return di.writeString("false") + + case 21: + return di.writeString("true") + + case 22: + return di.writeString("null") + + case 23: + return di.writeString("undefined") + + case 25, 26, 27: + return di.encodeFloat(ai, val) + + default: + if err := di.writeString("simple("); err != nil { + return err + } + if err := di.writeString(strconv.FormatUint(val, 10)); err != nil { + return err + } + return di.writeByte(')') + } + } + + return nil +} + +func (di *diagnose) writeByte(val byte) error { + return di.w.WriteByte(val) +} + +func (di *diagnose) writeString(val string) error { + _, err := di.w.WriteString(val) + return err +} + +// writeU16 format a rune as "\uxxxx" +func (di *diagnose) writeU16(val rune) error { + if err := di.writeString("\\u"); err != nil { + return err + } + b := make([]byte, 2) + b[0] = byte(val >> 8) + b[1] = byte(val) + return di.writeString(hex.EncodeToString(b)) +} + +var rawBase32Encoding = base32.StdEncoding.WithPadding(base32.NoPadding) +var rawBase32HexEncoding = base32.HexEncoding.WithPadding(base32.NoPadding) + +func (di *diagnose) encodeByteString(val []byte) error { + if len(val) > 0 { + if di.dm.byteStringText && utf8.Valid(val) { + return di.encodeTextString(string(val), '\'') + } + + if di.dm.byteStringEmbeddedCBOR { + di2 := newDiagnose(val, di.dm.decMode, di.dm) + // should always notating embedded CBOR sequence. + if str, err := di2.diag(true); err == nil { + if err := di.writeString("<<"); err != nil { + return err + } + if err := di.writeString(str); err != nil { + return err + } + return di.writeString(">>") + } + } + } + + switch di.dm.byteStringEncoding { + case ByteStringBase16Encoding: + if err := di.writeString("h'"); err != nil { + return err + } + + encoder := hex.NewEncoder(di.w) + if di.dm.byteStringHexWhitespace { + for i, b := range val { + if i > 0 { + if err := di.writeByte(' '); err != nil { + return err + } + } + if _, err := encoder.Write([]byte{b}); err != nil { + return err + } + } + } else { + if _, err := encoder.Write(val); err != nil { + return err + } + } + return di.writeByte('\'') + + case ByteStringBase32Encoding: + if err := di.writeString("b32'"); err != nil { + return err + } + encoder := base32.NewEncoder(rawBase32Encoding, di.w) + if _, err := encoder.Write(val); err != nil { + return err + } + encoder.Close() + return di.writeByte('\'') + + case ByteStringBase32HexEncoding: + if err := di.writeString("h32'"); err != nil { + return err + } + encoder := base32.NewEncoder(rawBase32HexEncoding, di.w) + if _, err := encoder.Write(val); err != nil { + return err + } + encoder.Close() + return di.writeByte('\'') + + case ByteStringBase64Encoding: + if err := di.writeString("b64'"); err != nil { + return err + } + encoder := base64.NewEncoder(base64.RawURLEncoding, di.w) + if _, err := encoder.Write(val); err != nil { + return err + } + encoder.Close() + return di.writeByte('\'') + + default: + return di.dm.byteStringEncoding.valid() + } +} + +var utf16SurrSelf = rune(0x10000) + +// quote should be either `'` or `"` +func (di *diagnose) encodeTextString(val string, quote byte) error { + if err := di.writeByte(quote); err != nil { + return err + } + + for i := 0; i < len(val); { + if b := val[i]; b < utf8.RuneSelf { + switch { + case b == '\t', b == '\n', b == '\r', b == '\\', b == quote: + if err := di.writeByte('\\'); err != nil { + return err + } + + switch b { + case '\t': + b = 't' + case '\n': + b = 'n' + case '\r': + b = 'r' + } + if err := di.writeByte(b); err != nil { + return err + } + + case b >= ' ' && b <= '~': + if err := di.writeByte(b); err != nil { + return err + } + + default: + if err := di.writeU16(rune(b)); err != nil { + return err + } + } + + i++ + continue + } + + c, size := utf8.DecodeRuneInString(val[i:]) + switch { + case c == utf8.RuneError: + // if err := di.writeU16(rune(val[i])); err != nil { + // return err + // } + return &SemanticError{"cbor: invalid UTF-8 string"} + + case c < utf16SurrSelf: + if err := di.writeU16(c); err != nil { + return err + } + + default: + c1, c2 := utf16.EncodeRune(c) + if err := di.writeU16(c1); err != nil { + return err + } + if err := di.writeU16(c2); err != nil { + return err + } + } + + i += size + } + + return di.writeByte(quote) +} + +func (di *diagnose) encodeFloat(ai byte, val uint64) error { + f64 := float64(0) + switch ai { + case 25: + f16 := float16.Frombits(uint16(val)) + switch { + case f16.IsNaN(): + return di.writeString("NaN") + case f16.IsInf(1): + return di.writeString("Infinity") + case f16.IsInf(-1): + return di.writeString("-Infinity") + default: + f64 = float64(f16.Float32()) + } + + case 26: + f32 := math.Float32frombits(uint32(val)) + switch { + case f32 != f32: + return di.writeString("NaN") + case f32 > math.MaxFloat32: + return di.writeString("Infinity") + case f32 < -math.MaxFloat32: + return di.writeString("-Infinity") + default: + f64 = float64(f32) + } + + case 27: + f64 = math.Float64frombits(val) + switch { + case f64 != f64: + return di.writeString("NaN") + case f64 > math.MaxFloat64: + return di.writeString("Infinity") + case f64 < -math.MaxFloat64: + return di.writeString("-Infinity") + } + } + // Use ES6 number to string conversion which should match most JSON generators. + // Inspired by https://github.com/golang/go/blob/4df10fba1687a6d4f51d7238a403f8f2298f6a16/src/encoding/json/encode.go#L585 + b := make([]byte, 0, 32) + if abs := math.Abs(f64); abs != 0 && (abs < 1e-6 || abs >= 1e21) { + b = strconv.AppendFloat(b, f64, 'e', -1, 64) + // clean up e-09 to e-9 + n := len(b) + if n >= 4 && string(b[n-4:n-1]) == "e-0" { + b = append(b[:n-2], b[n-1]) + } + } else { + b = strconv.AppendFloat(b, f64, 'f', -1, 64) + } + + // add decimal point and trailing zero if needed + if bytes.IndexByte(b, '.') < 0 { + if i := bytes.IndexByte(b, 'e'); i < 0 { + b = append(b, '.', '0') + } else { + b = append(b[:i+2], b[i:]...) + b[i] = '.' + b[i+1] = '0' + } + } + + if err := di.writeString(string(b)); err != nil { + return err + } + + if di.dm.floatPrecisionIndicator { + switch ai { + case 25: + return di.writeString("_1") + case 26: + return di.writeString("_2") + case 27: + return di.writeString("_3") + } + } + + return nil +} diff --git a/vendor/github.com/fxamacker/cbor/v2/doc.go b/vendor/github.com/fxamacker/cbor/v2/doc.go new file mode 100644 index 00000000..23f68b98 --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/doc.go @@ -0,0 +1,129 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +/* +Package cbor is a modern CBOR codec (RFC 8949 & RFC 7049) with CBOR tags, +Go struct tags (toarray/keyasint/omitempty), Core Deterministic Encoding, +CTAP2, Canonical CBOR, float64->32->16, and duplicate map key detection. + +Encoding options allow "preferred serialization" by encoding integers and floats +to their smallest forms (e.g. float16) when values fit. + +Struct tags like "keyasint", "toarray" and "omitempty" make CBOR data smaller +and easier to use with structs. + +For example, "toarray" tag makes struct fields encode to CBOR array elements. And +"keyasint" makes a field encode to an element of CBOR map with specified int key. + +Latest docs can be viewed at https://github.com/fxamacker/cbor#cbor-library-in-go + +# Basics + +The Quick Start guide is at https://github.com/fxamacker/cbor#quick-start + +Function signatures identical to encoding/json include: + + Marshal, Unmarshal, NewEncoder, NewDecoder, (*Encoder).Encode, (*Decoder).Decode. + +Standard interfaces include: + + BinaryMarshaler, BinaryUnmarshaler, Marshaler, and Unmarshaler. + +Custom encoding and decoding is possible by implementing standard interfaces for +user-defined Go types. + +Codec functions are available at package-level (using defaults options) or by +creating modes from options at runtime. + +"Mode" in this API means definite way of encoding (EncMode) or decoding (DecMode). + +EncMode and DecMode interfaces are created from EncOptions or DecOptions structs. + + em, err := cbor.EncOptions{...}.EncMode() + em, err := cbor.CanonicalEncOptions().EncMode() + em, err := cbor.CTAP2EncOptions().EncMode() + +Modes use immutable options to avoid side-effects and simplify concurrency. Behavior of +modes won't accidentally change at runtime after they're created. + +Modes are intended to be reused and are safe for concurrent use. + +EncMode and DecMode Interfaces + + // EncMode interface uses immutable options and is safe for concurrent use. + type EncMode interface { + Marshal(v interface{}) ([]byte, error) + NewEncoder(w io.Writer) *Encoder + EncOptions() EncOptions // returns copy of options + } + + // DecMode interface uses immutable options and is safe for concurrent use. + type DecMode interface { + Unmarshal(data []byte, v interface{}) error + NewDecoder(r io.Reader) *Decoder + DecOptions() DecOptions // returns copy of options + } + +Using Default Encoding Mode + + b, err := cbor.Marshal(v) + + encoder := cbor.NewEncoder(w) + err = encoder.Encode(v) + +Using Default Decoding Mode + + err := cbor.Unmarshal(b, &v) + + decoder := cbor.NewDecoder(r) + err = decoder.Decode(&v) + +Creating and Using Encoding Modes + + // Create EncOptions using either struct literal or a function. + opts := cbor.CanonicalEncOptions() + + // If needed, modify encoding options + opts.Time = cbor.TimeUnix + + // Create reusable EncMode interface with immutable options, safe for concurrent use. + em, err := opts.EncMode() + + // Use EncMode like encoding/json, with same function signatures. + b, err := em.Marshal(v) + // or + encoder := em.NewEncoder(w) + err := encoder.Encode(v) + + // NOTE: Both em.Marshal(v) and encoder.Encode(v) use encoding options + // specified during creation of em (encoding mode). + +# CBOR Options + +Predefined Encoding Options: https://github.com/fxamacker/cbor#predefined-encoding-options + +Encoding Options: https://github.com/fxamacker/cbor#encoding-options + +Decoding Options: https://github.com/fxamacker/cbor#decoding-options + +# Struct Tags + +Struct tags like `cbor:"name,omitempty"` and `json:"name,omitempty"` work as expected. +If both struct tags are specified then `cbor` is used. + +Struct tags like "keyasint", "toarray", and "omitempty" make it easy to use +very compact formats like COSE and CWT (CBOR Web Tokens) with structs. + +For example, "toarray" makes struct fields encode to array elements. And "keyasint" +makes struct fields encode to elements of CBOR map with int keys. + +https://raw.githubusercontent.com/fxamacker/images/master/cbor/v2.0.0/cbor_easy_api.png + +Struct tags are listed at https://github.com/fxamacker/cbor#struct-tags-1 + +# Tests and Fuzzing + +Over 375 tests are included in this package. Cover-guided fuzzing is handled by +a private fuzzer that replaced fxamacker/cbor-fuzz years ago. +*/ +package cbor diff --git a/vendor/github.com/fxamacker/cbor/v2/encode.go b/vendor/github.com/fxamacker/cbor/v2/encode.go new file mode 100644 index 00000000..86cc47ab --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/encode.go @@ -0,0 +1,1608 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +package cbor + +import ( + "bytes" + "encoding" + "encoding/binary" + "errors" + "io" + "math" + "math/big" + "reflect" + "sort" + "strconv" + "sync" + "time" + + "github.com/x448/float16" +) + +// Marshal returns the CBOR encoding of v using default encoding options. +// See EncOptions for encoding options. +// +// Marshal uses the following encoding rules: +// +// If value implements the Marshaler interface, Marshal calls its +// MarshalCBOR method. +// +// If value implements encoding.BinaryMarshaler, Marhsal calls its +// MarshalBinary method and encode it as CBOR byte string. +// +// Boolean values encode as CBOR booleans (type 7). +// +// Positive integer values encode as CBOR positive integers (type 0). +// +// Negative integer values encode as CBOR negative integers (type 1). +// +// Floating point values encode as CBOR floating points (type 7). +// +// String values encode as CBOR text strings (type 3). +// +// []byte values encode as CBOR byte strings (type 2). +// +// Array and slice values encode as CBOR arrays (type 4). +// +// Map values encode as CBOR maps (type 5). +// +// Struct values encode as CBOR maps (type 5). Each exported struct field +// becomes a pair with field name encoded as CBOR text string (type 3) and +// field value encoded based on its type. See struct tag option "keyasint" +// to encode field name as CBOR integer (type 0 and 1). Also see struct +// tag option "toarray" for special field "_" to encode struct values as +// CBOR array (type 4). +// +// Marshal supports format string stored under the "cbor" key in the struct +// field's tag. CBOR format string can specify the name of the field, +// "omitempty" and "keyasint" options, and special case "-" for field omission. +// If "cbor" key is absent, Marshal uses "json" key. +// +// Struct field name is treated as integer if it has "keyasint" option in +// its format string. The format string must specify an integer as its +// field name. +// +// Special struct field "_" is used to specify struct level options, such as +// "toarray". "toarray" option enables Go struct to be encoded as CBOR array. +// "omitempty" is disabled by "toarray" to ensure that the same number +// of elements are encoded every time. +// +// Anonymous struct fields are marshaled as if their exported fields +// were fields in the outer struct. Marshal follows the same struct fields +// visibility rules used by JSON encoding package. +// +// time.Time values encode as text strings specified in RFC3339 or numerical +// representation of seconds since January 1, 1970 UTC depending on +// EncOptions.Time setting. Also See EncOptions.TimeTag to encode +// time.Time as CBOR tag with tag number 0 or 1. +// +// big.Int values encode as CBOR integers (type 0 and 1) if values fit. +// Otherwise, big.Int values encode as CBOR bignums (tag 2 and 3). See +// EncOptions.BigIntConvert to always encode big.Int values as CBOR +// bignums. +// +// Pointer values encode as the value pointed to. +// +// Interface values encode as the value stored in the interface. +// +// Nil slice/map/pointer/interface values encode as CBOR nulls (type 7). +// +// Values of other types cannot be encoded in CBOR. Attempting +// to encode such a value causes Marshal to return an UnsupportedTypeError. +func Marshal(v interface{}) ([]byte, error) { + return defaultEncMode.Marshal(v) +} + +// Marshaler is the interface implemented by types that can marshal themselves +// into valid CBOR. +type Marshaler interface { + MarshalCBOR() ([]byte, error) +} + +// UnsupportedTypeError is returned by Marshal when attempting to encode value +// of an unsupported type. +type UnsupportedTypeError struct { + Type reflect.Type +} + +func (e *UnsupportedTypeError) Error() string { + return "cbor: unsupported type: " + e.Type.String() +} + +// UnsupportedValueError is returned by Marshal when attempting to encode an +// unsupported value. +type UnsupportedValueError struct { + msg string +} + +func (e *UnsupportedValueError) Error() string { + return "cbor: unsupported value: " + e.msg +} + +// SortMode identifies supported sorting order. +type SortMode int + +const ( + // SortNone means no sorting. + SortNone SortMode = 0 + + // SortLengthFirst causes map keys or struct fields to be sorted such that: + // - If two keys have different lengths, the shorter one sorts earlier; + // - If two keys have the same length, the one with the lower value in + // (byte-wise) lexical order sorts earlier. + // It is used in "Canonical CBOR" encoding in RFC 7049 3.9. + SortLengthFirst SortMode = 1 + + // SortBytewiseLexical causes map keys or struct fields to be sorted in the + // bytewise lexicographic order of their deterministic CBOR encodings. + // It is used in "CTAP2 Canonical CBOR" and "Core Deterministic Encoding" + // in RFC 7049bis. + SortBytewiseLexical SortMode = 2 + + // SortCanonical is used in "Canonical CBOR" encoding in RFC 7049 3.9. + SortCanonical SortMode = SortLengthFirst + + // SortCTAP2 is used in "CTAP2 Canonical CBOR". + SortCTAP2 SortMode = SortBytewiseLexical + + // SortCoreDeterministic is used in "Core Deterministic Encoding" in RFC 7049bis. + SortCoreDeterministic SortMode = SortBytewiseLexical + + maxSortMode SortMode = 3 +) + +func (sm SortMode) valid() bool { + return sm >= 0 && sm < maxSortMode +} + +// StringMode specifies how to encode Go string values. +type StringMode int + +const ( + // StringToTextString encodes Go string to CBOR text string (major type 3). + StringToTextString StringMode = iota + + // StringToByteString encodes Go string to CBOR byte string (major type 2). + StringToByteString +) + +func (st StringMode) cborType() (cborType, error) { + switch st { + case StringToTextString: + return cborTypeTextString, nil + case StringToByteString: + return cborTypeByteString, nil + } + return 0, errors.New("cbor: invalid StringType " + strconv.Itoa(int(st))) +} + +// ShortestFloatMode specifies which floating-point format should +// be used as the shortest possible format for CBOR encoding. +// It is not used for encoding Infinity and NaN values. +type ShortestFloatMode int + +const ( + // ShortestFloatNone makes float values encode without any conversion. + // This is the default for ShortestFloatMode in v1. + // E.g. a float32 in Go will encode to CBOR float32. And + // a float64 in Go will encode to CBOR float64. + ShortestFloatNone ShortestFloatMode = iota + + // ShortestFloat16 specifies float16 as the shortest form that preserves value. + // E.g. if float64 can convert to float32 while preserving value, then + // encoding will also try to convert float32 to float16. So a float64 might + // encode as CBOR float64, float32 or float16 depending on the value. + ShortestFloat16 + + maxShortestFloat +) + +func (sfm ShortestFloatMode) valid() bool { + return sfm >= 0 && sfm < maxShortestFloat +} + +// NaNConvertMode specifies how to encode NaN and overrides ShortestFloatMode. +// ShortestFloatMode is not used for encoding Infinity and NaN values. +type NaNConvertMode int + +const ( + // NaNConvert7e00 always encodes NaN to 0xf97e00 (CBOR float16 = 0x7e00). + NaNConvert7e00 NaNConvertMode = iota + + // NaNConvertNone never modifies or converts NaN to other representations + // (float64 NaN stays float64, etc. even if it can use float16 without losing + // any bits). + NaNConvertNone + + // NaNConvertPreserveSignal converts NaN to the smallest form that preserves + // value (quiet bit + payload) as described in RFC 7049bis Draft 12. + NaNConvertPreserveSignal + + // NaNConvertQuiet always forces quiet bit = 1 and shortest form that preserves + // NaN payload. + NaNConvertQuiet + + maxNaNConvert +) + +func (ncm NaNConvertMode) valid() bool { + return ncm >= 0 && ncm < maxNaNConvert +} + +// InfConvertMode specifies how to encode Infinity and overrides ShortestFloatMode. +// ShortestFloatMode is not used for encoding Infinity and NaN values. +type InfConvertMode int + +const ( + // InfConvertFloat16 always converts Inf to lossless IEEE binary16 (float16). + InfConvertFloat16 InfConvertMode = iota + + // InfConvertNone never converts (used by CTAP2 Canonical CBOR). + InfConvertNone + + maxInfConvert +) + +func (icm InfConvertMode) valid() bool { + return icm >= 0 && icm < maxInfConvert +} + +// TimeMode specifies how to encode time.Time values. +type TimeMode int + +const ( + // TimeUnix causes time.Time to be encoded as epoch time in integer with second precision. + TimeUnix TimeMode = iota + + // TimeUnixMicro causes time.Time to be encoded as epoch time in float-point rounded to microsecond precision. + TimeUnixMicro + + // TimeUnixDynamic causes time.Time to be encoded as integer if time.Time doesn't have fractional seconds, + // otherwise float-point rounded to microsecond precision. + TimeUnixDynamic + + // TimeRFC3339 causes time.Time to be encoded as RFC3339 formatted string with second precision. + TimeRFC3339 + + // TimeRFC3339Nano causes time.Time to be encoded as RFC3339 formatted string with nanosecond precision. + TimeRFC3339Nano + + maxTimeMode +) + +func (tm TimeMode) valid() bool { + return tm >= 0 && tm < maxTimeMode +} + +// BigIntConvertMode specifies how to encode big.Int values. +type BigIntConvertMode int + +const ( + // BigIntConvertShortest makes big.Int encode to CBOR integer if value fits. + // E.g. if big.Int value can be converted to CBOR integer while preserving + // value, encoder will encode it to CBOR integer (major type 0 or 1). + BigIntConvertShortest BigIntConvertMode = iota + + // BigIntConvertNone makes big.Int encode to CBOR bignum (tag 2 or 3) without + // converting it to another CBOR type. + BigIntConvertNone + + maxBigIntConvert +) + +func (bim BigIntConvertMode) valid() bool { + return bim >= 0 && bim < maxBigIntConvert +} + +// NilContainersMode specifies how to encode nil slices and maps. +type NilContainersMode int + +const ( + // NilContainerAsNull encodes nil slices and maps as CBOR null. + // This is the default. + NilContainerAsNull NilContainersMode = iota + + // NilContainerAsEmpty encodes nil slices and maps as + // empty container (CBOR bytestring, array, or map). + NilContainerAsEmpty + + maxNilContainersMode +) + +func (m NilContainersMode) valid() bool { + return m >= 0 && m < maxNilContainersMode +} + +// OmitEmptyMode specifies how to encode struct fields with omitempty tag. +// The default behavior omits if field value would encode as empty CBOR value. +type OmitEmptyMode int + +const ( + // OmitEmptyCBORValue specifies that struct fields tagged with "omitempty" + // should be omitted from encoding if the field would be encoded as an empty + // CBOR value, such as CBOR false, 0, 0.0, nil, empty byte, empty string, + // empty array, or empty map. + OmitEmptyCBORValue OmitEmptyMode = iota + + // OmitEmptyGoValue specifies that struct fields tagged with "omitempty" + // should be omitted from encoding if the field has an empty Go value, + // defined as false, 0, 0.0, a nil pointer, a nil interface value, and + // any empty array, slice, map, or string. + // This behavior is the same as the current (aka v1) encoding/json package + // included in Go. + OmitEmptyGoValue + + maxOmitEmptyMode +) + +func (om OmitEmptyMode) valid() bool { + return om >= 0 && om < maxOmitEmptyMode +} + +// FieldNameMode specifies the CBOR type to use when encoding struct field names. +type FieldNameMode int + +const ( + // FieldNameToTextString encodes struct fields to CBOR text string (major type 3). + FieldNameToTextString FieldNameMode = iota + + // FieldNameToTextString encodes struct fields to CBOR byte string (major type 2). + FieldNameToByteString + + maxFieldNameMode +) + +func (fnm FieldNameMode) valid() bool { + return fnm >= 0 && fnm < maxFieldNameMode +} + +// EncOptions specifies encoding options. +type EncOptions struct { + // Sort specifies sorting order. + Sort SortMode + + // ShortestFloat specifies the shortest floating-point encoding that preserves + // the value being encoded. + ShortestFloat ShortestFloatMode + + // NaNConvert specifies how to encode NaN and it overrides ShortestFloatMode. + NaNConvert NaNConvertMode + + // InfConvert specifies how to encode Inf and it overrides ShortestFloatMode. + InfConvert InfConvertMode + + // BigIntConvert specifies how to encode big.Int values. + BigIntConvert BigIntConvertMode + + // Time specifies how to encode time.Time. + Time TimeMode + + // TimeTag allows time.Time to be encoded with a tag number. + // RFC3339 format gets tag number 0, and numeric epoch time tag number 1. + TimeTag EncTagMode + + // IndefLength specifies whether to allow indefinite length CBOR items. + IndefLength IndefLengthMode + + // NilContainers specifies how to encode nil slices and maps. + NilContainers NilContainersMode + + // TagsMd specifies whether to allow CBOR tags (major type 6). + TagsMd TagsMode + + // OmitEmptyMode specifies how to encode struct fields with omitempty tag. + OmitEmpty OmitEmptyMode + + // String specifies which CBOR type to use when encoding Go strings. + // - CBOR text string (major type 3) is default + // - CBOR byte string (major type 2) + String StringMode + + // FieldName specifies the CBOR type to use when encoding struct field names. + FieldName FieldNameMode +} + +// CanonicalEncOptions returns EncOptions for "Canonical CBOR" encoding, +// defined in RFC 7049 Section 3.9 with the following rules: +// +// 1. "Integers must be as small as possible." +// 2. "The expression of lengths in major types 2 through 5 must be as short as possible." +// 3. The keys in every map must be sorted in length-first sorting order. +// See SortLengthFirst for details. +// 4. "Indefinite-length items must be made into definite-length items." +// 5. "If a protocol allows for IEEE floats, then additional canonicalization rules might +// need to be added. One example rule might be to have all floats start as a 64-bit +// float, then do a test conversion to a 32-bit float; if the result is the same numeric +// value, use the shorter value and repeat the process with a test conversion to a +// 16-bit float. (This rule selects 16-bit float for positive and negative Infinity +// as well.) Also, there are many representations for NaN. If NaN is an allowed value, +// it must always be represented as 0xf97e00." +func CanonicalEncOptions() EncOptions { + return EncOptions{ + Sort: SortCanonical, + ShortestFloat: ShortestFloat16, + NaNConvert: NaNConvert7e00, + InfConvert: InfConvertFloat16, + IndefLength: IndefLengthForbidden, + } +} + +// CTAP2EncOptions returns EncOptions for "CTAP2 Canonical CBOR" encoding, +// defined in CTAP specification, with the following rules: +// +// 1. "Integers must be encoded as small as possible." +// 2. "The representations of any floating-point values are not changed." +// 3. "The expression of lengths in major types 2 through 5 must be as short as possible." +// 4. "Indefinite-length items must be made into definite-length items."" +// 5. The keys in every map must be sorted in bytewise lexicographic order. +// See SortBytewiseLexical for details. +// 6. "Tags as defined in Section 2.4 in [RFC7049] MUST NOT be present." +func CTAP2EncOptions() EncOptions { + return EncOptions{ + Sort: SortCTAP2, + ShortestFloat: ShortestFloatNone, + NaNConvert: NaNConvertNone, + InfConvert: InfConvertNone, + IndefLength: IndefLengthForbidden, + TagsMd: TagsForbidden, + } +} + +// CoreDetEncOptions returns EncOptions for "Core Deterministic" encoding, +// defined in RFC 7049bis with the following rules: +// +// 1. "Preferred serialization MUST be used. In particular, this means that arguments +// (see Section 3) for integers, lengths in major types 2 through 5, and tags MUST +// be as short as possible" +// "Floating point values also MUST use the shortest form that preserves the value" +// 2. "Indefinite-length items MUST NOT appear." +// 3. "The keys in every map MUST be sorted in the bytewise lexicographic order of +// their deterministic encodings." +func CoreDetEncOptions() EncOptions { + return EncOptions{ + Sort: SortCoreDeterministic, + ShortestFloat: ShortestFloat16, + NaNConvert: NaNConvert7e00, + InfConvert: InfConvertFloat16, + IndefLength: IndefLengthForbidden, + } +} + +// PreferredUnsortedEncOptions returns EncOptions for "Preferred Serialization" encoding, +// defined in RFC 7049bis with the following rules: +// +// 1. "The preferred serialization always uses the shortest form of representing the argument +// (Section 3);" +// 2. "it also uses the shortest floating-point encoding that preserves the value being +// encoded (see Section 5.5)." +// "The preferred encoding for a floating-point value is the shortest floating-point encoding +// that preserves its value, e.g., 0xf94580 for the number 5.5, and 0xfa45ad9c00 for the +// number 5555.5, unless the CBOR-based protocol specifically excludes the use of the shorter +// floating-point encodings. For NaN values, a shorter encoding is preferred if zero-padding +// the shorter significand towards the right reconstitutes the original NaN value (for many +// applications, the single NaN encoding 0xf97e00 will suffice)." +// 3. "Definite length encoding is preferred whenever the length is known at the time the +// serialization of the item starts." +func PreferredUnsortedEncOptions() EncOptions { + return EncOptions{ + Sort: SortNone, + ShortestFloat: ShortestFloat16, + NaNConvert: NaNConvert7e00, + InfConvert: InfConvertFloat16, + } +} + +// EncMode returns EncMode with immutable options and no tags (safe for concurrency). +func (opts EncOptions) EncMode() (EncMode, error) { + return opts.encMode() +} + +// EncModeWithTags returns EncMode with options and tags that are both immutable (safe for concurrency). +func (opts EncOptions) EncModeWithTags(tags TagSet) (EncMode, error) { + if opts.TagsMd == TagsForbidden { + return nil, errors.New("cbor: cannot create EncMode with TagSet when TagsMd is TagsForbidden") + } + if tags == nil { + return nil, errors.New("cbor: cannot create EncMode with nil value as TagSet") + } + em, err := opts.encMode() + if err != nil { + return nil, err + } + // Copy tags + ts := tagSet(make(map[reflect.Type]*tagItem)) + syncTags := tags.(*syncTagSet) + syncTags.RLock() + for contentType, tag := range syncTags.t { + if tag.opts.EncTag != EncTagNone { + ts[contentType] = tag + } + } + syncTags.RUnlock() + if len(ts) > 0 { + em.tags = ts + } + return em, nil +} + +// EncModeWithSharedTags returns EncMode with immutable options and mutable shared tags (safe for concurrency). +func (opts EncOptions) EncModeWithSharedTags(tags TagSet) (EncMode, error) { + if opts.TagsMd == TagsForbidden { + return nil, errors.New("cbor: cannot create EncMode with TagSet when TagsMd is TagsForbidden") + } + if tags == nil { + return nil, errors.New("cbor: cannot create EncMode with nil value as TagSet") + } + em, err := opts.encMode() + if err != nil { + return nil, err + } + em.tags = tags + return em, nil +} + +func (opts EncOptions) encMode() (*encMode, error) { + if !opts.Sort.valid() { + return nil, errors.New("cbor: invalid SortMode " + strconv.Itoa(int(opts.Sort))) + } + if !opts.ShortestFloat.valid() { + return nil, errors.New("cbor: invalid ShortestFloatMode " + strconv.Itoa(int(opts.ShortestFloat))) + } + if !opts.NaNConvert.valid() { + return nil, errors.New("cbor: invalid NaNConvertMode " + strconv.Itoa(int(opts.NaNConvert))) + } + if !opts.InfConvert.valid() { + return nil, errors.New("cbor: invalid InfConvertMode " + strconv.Itoa(int(opts.InfConvert))) + } + if !opts.BigIntConvert.valid() { + return nil, errors.New("cbor: invalid BigIntConvertMode " + strconv.Itoa(int(opts.BigIntConvert))) + } + if !opts.Time.valid() { + return nil, errors.New("cbor: invalid TimeMode " + strconv.Itoa(int(opts.Time))) + } + if !opts.TimeTag.valid() { + return nil, errors.New("cbor: invalid TimeTag " + strconv.Itoa(int(opts.TimeTag))) + } + if !opts.IndefLength.valid() { + return nil, errors.New("cbor: invalid IndefLength " + strconv.Itoa(int(opts.IndefLength))) + } + if !opts.NilContainers.valid() { + return nil, errors.New("cbor: invalid NilContainers " + strconv.Itoa(int(opts.NilContainers))) + } + if !opts.TagsMd.valid() { + return nil, errors.New("cbor: invalid TagsMd " + strconv.Itoa(int(opts.TagsMd))) + } + if opts.TagsMd == TagsForbidden && opts.TimeTag == EncTagRequired { + return nil, errors.New("cbor: cannot set TagsMd to TagsForbidden when TimeTag is EncTagRequired") + } + if !opts.OmitEmpty.valid() { + return nil, errors.New("cbor: invalid OmitEmpty " + strconv.Itoa(int(opts.OmitEmpty))) + } + stringMajorType, err := opts.String.cborType() + if err != nil { + return nil, err + } + if !opts.FieldName.valid() { + return nil, errors.New("cbor: invalid FieldName " + strconv.Itoa(int(opts.FieldName))) + } + em := encMode{ + sort: opts.Sort, + shortestFloat: opts.ShortestFloat, + nanConvert: opts.NaNConvert, + infConvert: opts.InfConvert, + bigIntConvert: opts.BigIntConvert, + time: opts.Time, + timeTag: opts.TimeTag, + indefLength: opts.IndefLength, + nilContainers: opts.NilContainers, + tagsMd: opts.TagsMd, + omitEmpty: opts.OmitEmpty, + stringType: opts.String, + stringMajorType: stringMajorType, + fieldName: opts.FieldName, + } + return &em, nil +} + +// EncMode is the main interface for CBOR encoding. +type EncMode interface { + Marshal(v interface{}) ([]byte, error) + NewEncoder(w io.Writer) *Encoder + EncOptions() EncOptions +} + +type encMode struct { + tags tagProvider + sort SortMode + shortestFloat ShortestFloatMode + nanConvert NaNConvertMode + infConvert InfConvertMode + bigIntConvert BigIntConvertMode + time TimeMode + timeTag EncTagMode + indefLength IndefLengthMode + nilContainers NilContainersMode + tagsMd TagsMode + omitEmpty OmitEmptyMode + stringType StringMode + stringMajorType cborType + fieldName FieldNameMode +} + +var defaultEncMode, _ = EncOptions{}.encMode() + +// EncOptions returns user specified options used to create this EncMode. +func (em *encMode) EncOptions() EncOptions { + return EncOptions{ + Sort: em.sort, + ShortestFloat: em.shortestFloat, + NaNConvert: em.nanConvert, + InfConvert: em.infConvert, + BigIntConvert: em.bigIntConvert, + Time: em.time, + TimeTag: em.timeTag, + IndefLength: em.indefLength, + NilContainers: em.nilContainers, + TagsMd: em.tagsMd, + OmitEmpty: em.omitEmpty, + String: em.stringType, + FieldName: em.fieldName, + } +} + +func (em *encMode) encTagBytes(t reflect.Type) []byte { + if em.tags != nil { + if tagItem := em.tags.getTagItemFromType(t); tagItem != nil { + return tagItem.cborTagNum + } + } + return nil +} + +// Marshal returns the CBOR encoding of v using em encoding mode. +// +// See the documentation for Marshal for details. +func (em *encMode) Marshal(v interface{}) ([]byte, error) { + e := getEncoderBuffer() + + if err := encode(e, em, reflect.ValueOf(v)); err != nil { + putEncoderBuffer(e) + return nil, err + } + + buf := make([]byte, e.Len()) + copy(buf, e.Bytes()) + + putEncoderBuffer(e) + return buf, nil +} + +// NewEncoder returns a new encoder that writes to w using em EncMode. +func (em *encMode) NewEncoder(w io.Writer) *Encoder { + return &Encoder{w: w, em: em} +} + +type encoderBuffer struct { + bytes.Buffer + scratch [16]byte +} + +// encoderBufferPool caches unused encoderBuffer objects for later reuse. +var encoderBufferPool = sync.Pool{ + New: func() interface{} { + e := new(encoderBuffer) + e.Grow(32) // TODO: make this configurable + return e + }, +} + +func getEncoderBuffer() *encoderBuffer { + return encoderBufferPool.Get().(*encoderBuffer) +} + +func putEncoderBuffer(e *encoderBuffer) { + e.Reset() + encoderBufferPool.Put(e) +} + +type encodeFunc func(e *encoderBuffer, em *encMode, v reflect.Value) error +type isEmptyFunc func(em *encMode, v reflect.Value) (empty bool, err error) + +var ( + cborFalse = []byte{0xf4} + cborTrue = []byte{0xf5} + cborNil = []byte{0xf6} + cborNaN = []byte{0xf9, 0x7e, 0x00} + cborPositiveInfinity = []byte{0xf9, 0x7c, 0x00} + cborNegativeInfinity = []byte{0xf9, 0xfc, 0x00} +) + +func encode(e *encoderBuffer, em *encMode, v reflect.Value) error { + if !v.IsValid() { + // v is zero value + e.Write(cborNil) + return nil + } + vt := v.Type() + f, _ := getEncodeFunc(vt) + if f == nil { + return &UnsupportedTypeError{vt} + } + + return f(e, em, v) +} + +func encodeBool(e *encoderBuffer, em *encMode, v reflect.Value) error { + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + b := cborFalse + if v.Bool() { + b = cborTrue + } + e.Write(b) + return nil +} + +func encodeInt(e *encoderBuffer, em *encMode, v reflect.Value) error { + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + i := v.Int() + if i >= 0 { + encodeHead(e, byte(cborTypePositiveInt), uint64(i)) + return nil + } + i = i*(-1) - 1 + encodeHead(e, byte(cborTypeNegativeInt), uint64(i)) + return nil +} + +func encodeUint(e *encoderBuffer, em *encMode, v reflect.Value) error { + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + encodeHead(e, byte(cborTypePositiveInt), v.Uint()) + return nil +} + +func encodeFloat(e *encoderBuffer, em *encMode, v reflect.Value) error { + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + f64 := v.Float() + if math.IsNaN(f64) { + return encodeNaN(e, em, v) + } + if math.IsInf(f64, 0) { + return encodeInf(e, em, v) + } + fopt := em.shortestFloat + if v.Kind() == reflect.Float64 && (fopt == ShortestFloatNone || cannotFitFloat32(f64)) { + // Encode float64 + // Don't use encodeFloat64() because it cannot be inlined. + e.scratch[0] = byte(cborTypePrimitives) | byte(27) + binary.BigEndian.PutUint64(e.scratch[1:], math.Float64bits(f64)) + e.Write(e.scratch[:9]) + return nil + } + + f32 := float32(f64) + if fopt == ShortestFloat16 { + var f16 float16.Float16 + p := float16.PrecisionFromfloat32(f32) + if p == float16.PrecisionExact { + // Roundtrip float32->float16->float32 test isn't needed. + f16 = float16.Fromfloat32(f32) + } else if p == float16.PrecisionUnknown { + // Try roundtrip float32->float16->float32 to determine if float32 can fit into float16. + f16 = float16.Fromfloat32(f32) + if f16.Float32() == f32 { + p = float16.PrecisionExact + } + } + if p == float16.PrecisionExact { + // Encode float16 + // Don't use encodeFloat16() because it cannot be inlined. + e.scratch[0] = byte(cborTypePrimitives) | byte(25) + binary.BigEndian.PutUint16(e.scratch[1:], uint16(f16)) + e.Write(e.scratch[:3]) + return nil + } + } + + // Encode float32 + // Don't use encodeFloat32() because it cannot be inlined. + e.scratch[0] = byte(cborTypePrimitives) | byte(26) + binary.BigEndian.PutUint32(e.scratch[1:], math.Float32bits(f32)) + e.Write(e.scratch[:5]) + return nil +} + +func encodeInf(e *encoderBuffer, em *encMode, v reflect.Value) error { + f64 := v.Float() + if em.infConvert == InfConvertFloat16 { + if f64 > 0 { + e.Write(cborPositiveInfinity) + } else { + e.Write(cborNegativeInfinity) + } + return nil + } + if v.Kind() == reflect.Float64 { + return encodeFloat64(e, f64) + } + return encodeFloat32(e, float32(f64)) +} + +func encodeNaN(e *encoderBuffer, em *encMode, v reflect.Value) error { + switch em.nanConvert { + case NaNConvert7e00: + e.Write(cborNaN) + return nil + + case NaNConvertNone: + if v.Kind() == reflect.Float64 { + return encodeFloat64(e, v.Float()) + } + f32 := float32NaNFromReflectValue(v) + return encodeFloat32(e, f32) + + default: // NaNConvertPreserveSignal, NaNConvertQuiet + if v.Kind() == reflect.Float64 { + f64 := v.Float() + f64bits := math.Float64bits(f64) + if em.nanConvert == NaNConvertQuiet && f64bits&(1<<51) == 0 { + f64bits |= 1 << 51 // Set quiet bit = 1 + f64 = math.Float64frombits(f64bits) + } + // The lower 29 bits are dropped when converting from float64 to float32. + if f64bits&0x1fffffff != 0 { + // Encode NaN as float64 because dropped coef bits from float64 to float32 are not all 0s. + return encodeFloat64(e, f64) + } + // Create float32 from float64 manually because float32(f64) always turns on NaN's quiet bits. + sign := uint32(f64bits>>32) & (1 << 31) + exp := uint32(0x7f800000) + coef := uint32((f64bits & 0xfffffffffffff) >> 29) + f32bits := sign | exp | coef + f32 := math.Float32frombits(f32bits) + // The lower 13 bits are dropped when converting from float32 to float16. + if f32bits&0x1fff != 0 { + // Encode NaN as float32 because dropped coef bits from float32 to float16 are not all 0s. + return encodeFloat32(e, f32) + } + // Encode NaN as float16 + f16, _ := float16.FromNaN32ps(f32) // Ignore err because it only returns error when f32 is not a NaN. + return encodeFloat16(e, f16) + } + + f32 := float32NaNFromReflectValue(v) + f32bits := math.Float32bits(f32) + if em.nanConvert == NaNConvertQuiet && f32bits&(1<<22) == 0 { + f32bits |= 1 << 22 // Set quiet bit = 1 + f32 = math.Float32frombits(f32bits) + } + // The lower 13 bits are dropped coef bits when converting from float32 to float16. + if f32bits&0x1fff != 0 { + // Encode NaN as float32 because dropped coef bits from float32 to float16 are not all 0s. + return encodeFloat32(e, f32) + } + f16, _ := float16.FromNaN32ps(f32) // Ignore err because it only returns error when f32 is not a NaN. + return encodeFloat16(e, f16) + } +} + +func encodeFloat16(e *encoderBuffer, f16 float16.Float16) error { + e.scratch[0] = byte(cborTypePrimitives) | byte(25) + binary.BigEndian.PutUint16(e.scratch[1:], uint16(f16)) + e.Write(e.scratch[:3]) + return nil +} + +func encodeFloat32(e *encoderBuffer, f32 float32) error { + e.scratch[0] = byte(cborTypePrimitives) | byte(26) + binary.BigEndian.PutUint32(e.scratch[1:], math.Float32bits(f32)) + e.Write(e.scratch[:5]) + return nil +} + +func encodeFloat64(e *encoderBuffer, f64 float64) error { + e.scratch[0] = byte(cborTypePrimitives) | byte(27) + binary.BigEndian.PutUint64(e.scratch[1:], math.Float64bits(f64)) + e.Write(e.scratch[:9]) + return nil +} + +func encodeByteString(e *encoderBuffer, em *encMode, v reflect.Value) error { + vk := v.Kind() + if vk == reflect.Slice && v.IsNil() && em.nilContainers == NilContainerAsNull { + e.Write(cborNil) + return nil + } + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + slen := v.Len() + if slen == 0 { + return e.WriteByte(byte(cborTypeByteString)) + } + encodeHead(e, byte(cborTypeByteString), uint64(slen)) + if vk == reflect.Array { + for i := 0; i < slen; i++ { + e.WriteByte(byte(v.Index(i).Uint())) + } + return nil + } + e.Write(v.Bytes()) + return nil +} + +func encodeString(e *encoderBuffer, em *encMode, v reflect.Value) error { + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + s := v.String() + encodeHead(e, byte(em.stringMajorType), uint64(len(s))) + e.WriteString(s) + return nil +} + +type arrayEncodeFunc struct { + f encodeFunc +} + +func (ae arrayEncodeFunc) encode(e *encoderBuffer, em *encMode, v reflect.Value) error { + if v.Kind() == reflect.Slice && v.IsNil() && em.nilContainers == NilContainerAsNull { + e.Write(cborNil) + return nil + } + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + alen := v.Len() + if alen == 0 { + return e.WriteByte(byte(cborTypeArray)) + } + encodeHead(e, byte(cborTypeArray), uint64(alen)) + for i := 0; i < alen; i++ { + if err := ae.f(e, em, v.Index(i)); err != nil { + return err + } + } + return nil +} + +// encodeKeyValueFunc encodes key/value pairs in map (v). +// If kvs is provided (having the same length as v), length of encoded key and value are stored in kvs. +// kvs is used for canonical encoding of map. +type encodeKeyValueFunc func(e *encoderBuffer, em *encMode, v reflect.Value, kvs []keyValue) error + +type mapEncodeFunc struct { + e encodeKeyValueFunc +} + +func (me mapEncodeFunc) encode(e *encoderBuffer, em *encMode, v reflect.Value) error { + if v.IsNil() && em.nilContainers == NilContainerAsNull { + e.Write(cborNil) + return nil + } + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + mlen := v.Len() + if mlen == 0 { + return e.WriteByte(byte(cborTypeMap)) + } + if em.sort != SortNone { + return me.encodeCanonical(e, em, v) + } + encodeHead(e, byte(cborTypeMap), uint64(mlen)) + + return me.e(e, em, v, nil) +} + +type keyValue struct { + keyCBORData, keyValueCBORData []byte + keyLen, keyValueLen int +} + +type bytewiseKeyValueSorter struct { + kvs []keyValue +} + +func (x *bytewiseKeyValueSorter) Len() int { + return len(x.kvs) +} + +func (x *bytewiseKeyValueSorter) Swap(i, j int) { + x.kvs[i], x.kvs[j] = x.kvs[j], x.kvs[i] +} + +func (x *bytewiseKeyValueSorter) Less(i, j int) bool { + return bytes.Compare(x.kvs[i].keyCBORData, x.kvs[j].keyCBORData) <= 0 +} + +type lengthFirstKeyValueSorter struct { + kvs []keyValue +} + +func (x *lengthFirstKeyValueSorter) Len() int { + return len(x.kvs) +} + +func (x *lengthFirstKeyValueSorter) Swap(i, j int) { + x.kvs[i], x.kvs[j] = x.kvs[j], x.kvs[i] +} + +func (x *lengthFirstKeyValueSorter) Less(i, j int) bool { + if len(x.kvs[i].keyCBORData) != len(x.kvs[j].keyCBORData) { + return len(x.kvs[i].keyCBORData) < len(x.kvs[j].keyCBORData) + } + return bytes.Compare(x.kvs[i].keyCBORData, x.kvs[j].keyCBORData) <= 0 +} + +var keyValuePool = sync.Pool{} + +func getKeyValues(length int) *[]keyValue { + v := keyValuePool.Get() + if v == nil { + y := make([]keyValue, length) + return &y + } + x := v.(*[]keyValue) + if cap(*x) >= length { + *x = (*x)[:length] + return x + } + // []keyValue from the pool does not have enough capacity. + // Return it back to the pool and create a new one. + keyValuePool.Put(x) + y := make([]keyValue, length) + return &y +} + +func putKeyValues(x *[]keyValue) { + *x = (*x)[:0] + keyValuePool.Put(x) +} + +func (me mapEncodeFunc) encodeCanonical(e *encoderBuffer, em *encMode, v reflect.Value) error { + kve := getEncoderBuffer() // accumulated cbor encoded key-values + defer putEncoderBuffer(kve) + + kvsp := getKeyValues(v.Len()) // for sorting keys + defer putKeyValues(kvsp) + + kvs := *kvsp + + err := me.e(kve, em, v, kvs) + if err != nil { + return err + } + + b := kve.Bytes() + for i, off := 0, 0; i < len(kvs); i++ { + kvs[i].keyCBORData = b[off : off+kvs[i].keyLen] + kvs[i].keyValueCBORData = b[off : off+kvs[i].keyValueLen] + off += kvs[i].keyValueLen + } + + if em.sort == SortBytewiseLexical { + sort.Sort(&bytewiseKeyValueSorter{kvs}) + } else { + sort.Sort(&lengthFirstKeyValueSorter{kvs}) + } + + encodeHead(e, byte(cborTypeMap), uint64(len(kvs))) + for i := 0; i < len(kvs); i++ { + e.Write(kvs[i].keyValueCBORData) + } + + return nil +} + +func encodeStructToArray(e *encoderBuffer, em *encMode, v reflect.Value) (err error) { + structType, err := getEncodingStructType(v.Type()) + if err != nil { + return err + } + + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + + flds := structType.fields + + encodeHead(e, byte(cborTypeArray), uint64(len(flds))) + for i := 0; i < len(flds); i++ { + f := flds[i] + + var fv reflect.Value + if len(f.idx) == 1 { + fv = v.Field(f.idx[0]) + } else { + // Get embedded field value. No error is expected. + fv, _ = getFieldValue(v, f.idx, func(v reflect.Value) (reflect.Value, error) { + // Write CBOR nil for null pointer to embedded struct + e.Write(cborNil) + return reflect.Value{}, nil + }) + if !fv.IsValid() { + continue + } + } + + if err := f.ef(e, em, fv); err != nil { + return err + } + } + return nil +} + +func encodeFixedLengthStruct(e *encoderBuffer, em *encMode, v reflect.Value, flds fields) error { + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + + encodeHead(e, byte(cborTypeMap), uint64(len(flds))) + + for i := 0; i < len(flds); i++ { + f := flds[i] + if !f.keyAsInt && em.fieldName == FieldNameToByteString { + e.Write(f.cborNameByteString) + } else { // int or text string + e.Write(f.cborName) + } + + fv := v.Field(f.idx[0]) + if err := f.ef(e, em, fv); err != nil { + return err + } + } + + return nil +} + +func encodeStruct(e *encoderBuffer, em *encMode, v reflect.Value) (err error) { + structType, err := getEncodingStructType(v.Type()) + if err != nil { + return err + } + + flds := structType.getFields(em) + + if structType.fixedLength { + return encodeFixedLengthStruct(e, em, v, flds) + } + + kve := getEncoderBuffer() // encode key-value pairs based on struct field tag options + kvcount := 0 + for i := 0; i < len(flds); i++ { + f := flds[i] + + var fv reflect.Value + if len(f.idx) == 1 { + fv = v.Field(f.idx[0]) + } else { + // Get embedded field value. No error is expected. + fv, _ = getFieldValue(v, f.idx, func(v reflect.Value) (reflect.Value, error) { + // Skip null pointer to embedded struct + return reflect.Value{}, nil + }) + if !fv.IsValid() { + continue + } + } + if f.omitEmpty { + empty, err := f.ief(em, fv) + if err != nil { + putEncoderBuffer(kve) + return err + } + if empty { + continue + } + } + + if !f.keyAsInt && em.fieldName == FieldNameToByteString { + kve.Write(f.cborNameByteString) + } else { // int or text string + kve.Write(f.cborName) + } + + if err := f.ef(kve, em, fv); err != nil { + putEncoderBuffer(kve) + return err + } + kvcount++ + } + + if b := em.encTagBytes(v.Type()); b != nil { + e.Write(b) + } + + encodeHead(e, byte(cborTypeMap), uint64(kvcount)) + e.Write(kve.Bytes()) + + putEncoderBuffer(kve) + return nil +} + +func encodeIntf(e *encoderBuffer, em *encMode, v reflect.Value) error { + if v.IsNil() { + e.Write(cborNil) + return nil + } + return encode(e, em, v.Elem()) +} + +func encodeTime(e *encoderBuffer, em *encMode, v reflect.Value) error { + t := v.Interface().(time.Time) + if t.IsZero() { + e.Write(cborNil) // Even if tag is required, encode as CBOR null. + return nil + } + if em.timeTag == EncTagRequired { + tagNumber := 1 + if em.time == TimeRFC3339 || em.time == TimeRFC3339Nano { + tagNumber = 0 + } + encodeHead(e, byte(cborTypeTag), uint64(tagNumber)) + } + switch em.time { + case TimeUnix: + secs := t.Unix() + return encodeInt(e, em, reflect.ValueOf(secs)) + case TimeUnixMicro: + t = t.UTC().Round(time.Microsecond) + f := float64(t.UnixNano()) / 1e9 + return encodeFloat(e, em, reflect.ValueOf(f)) + case TimeUnixDynamic: + t = t.UTC().Round(time.Microsecond) + secs, nsecs := t.Unix(), uint64(t.Nanosecond()) + if nsecs == 0 { + return encodeInt(e, em, reflect.ValueOf(secs)) + } + f := float64(secs) + float64(nsecs)/1e9 + return encodeFloat(e, em, reflect.ValueOf(f)) + case TimeRFC3339: + s := t.Format(time.RFC3339) + return encodeString(e, em, reflect.ValueOf(s)) + default: // TimeRFC3339Nano + s := t.Format(time.RFC3339Nano) + return encodeString(e, em, reflect.ValueOf(s)) + } +} + +func encodeBigInt(e *encoderBuffer, em *encMode, v reflect.Value) error { + vbi := v.Interface().(big.Int) + sign := vbi.Sign() + bi := new(big.Int).SetBytes(vbi.Bytes()) // bi is absolute value of v + if sign < 0 { + // For negative number, convert to CBOR encoded number (-v-1). + bi.Sub(bi, big.NewInt(1)) + } + + if em.bigIntConvert == BigIntConvertShortest { + if bi.IsUint64() { + if sign >= 0 { + // Encode as CBOR pos int (major type 0) + encodeHead(e, byte(cborTypePositiveInt), bi.Uint64()) + return nil + } + // Encode as CBOR neg int (major type 1) + encodeHead(e, byte(cborTypeNegativeInt), bi.Uint64()) + return nil + } + } + + tagNum := 2 + if sign < 0 { + tagNum = 3 + } + // Write tag number + encodeHead(e, byte(cborTypeTag), uint64(tagNum)) + // Write bignum byte string + b := bi.Bytes() + encodeHead(e, byte(cborTypeByteString), uint64(len(b))) + e.Write(b) + return nil +} + +func encodeBinaryMarshalerType(e *encoderBuffer, em *encMode, v reflect.Value) error { + vt := v.Type() + m, ok := v.Interface().(encoding.BinaryMarshaler) + if !ok { + pv := reflect.New(vt) + pv.Elem().Set(v) + m = pv.Interface().(encoding.BinaryMarshaler) + } + data, err := m.MarshalBinary() + if err != nil { + return err + } + if b := em.encTagBytes(vt); b != nil { + e.Write(b) + } + encodeHead(e, byte(cborTypeByteString), uint64(len(data))) + e.Write(data) + return nil +} + +func encodeMarshalerType(e *encoderBuffer, em *encMode, v reflect.Value) error { + if em.tagsMd == TagsForbidden && v.Type() == typeRawTag { + return errors.New("cbor: cannot encode cbor.RawTag when TagsMd is TagsForbidden") + } + m, ok := v.Interface().(Marshaler) + if !ok { + pv := reflect.New(v.Type()) + pv.Elem().Set(v) + m = pv.Interface().(Marshaler) + } + data, err := m.MarshalCBOR() + if err != nil { + return err + } + e.Write(data) + return nil +} + +func encodeTag(e *encoderBuffer, em *encMode, v reflect.Value) error { + if em.tagsMd == TagsForbidden { + return errors.New("cbor: cannot encode cbor.Tag when TagsMd is TagsForbidden") + } + + t := v.Interface().(Tag) + + if t.Number == 0 && t.Content == nil { + // Marshal uninitialized cbor.Tag + e.Write(cborNil) + return nil + } + + // Marshal tag number + encodeHead(e, byte(cborTypeTag), t.Number) + + // Marshal tag content + return encode(e, em, reflect.ValueOf(t.Content)) +} + +func encodeHead(e *encoderBuffer, t byte, n uint64) { + if n <= 23 { + e.WriteByte(t | byte(n)) + return + } + if n <= math.MaxUint8 { + e.scratch[0] = t | byte(24) + e.scratch[1] = byte(n) + e.Write(e.scratch[:2]) + return + } + if n <= math.MaxUint16 { + e.scratch[0] = t | byte(25) + binary.BigEndian.PutUint16(e.scratch[1:], uint16(n)) + e.Write(e.scratch[:3]) + return + } + if n <= math.MaxUint32 { + e.scratch[0] = t | byte(26) + binary.BigEndian.PutUint32(e.scratch[1:], uint32(n)) + e.Write(e.scratch[:5]) + return + } + e.scratch[0] = t | byte(27) + binary.BigEndian.PutUint64(e.scratch[1:], n) + e.Write(e.scratch[:9]) +} + +var ( + typeMarshaler = reflect.TypeOf((*Marshaler)(nil)).Elem() + typeBinaryMarshaler = reflect.TypeOf((*encoding.BinaryMarshaler)(nil)).Elem() + typeRawMessage = reflect.TypeOf(RawMessage(nil)) + typeByteString = reflect.TypeOf(ByteString("")) +) + +func getEncodeFuncInternal(t reflect.Type) (encodeFunc, isEmptyFunc) { + k := t.Kind() + if k == reflect.Ptr { + return getEncodeIndirectValueFunc(t), isEmptyPtr + } + switch t { + case typeSimpleValue: + return encodeMarshalerType, isEmptyUint + case typeTag: + return encodeTag, alwaysNotEmpty + case typeTime: + return encodeTime, alwaysNotEmpty + case typeBigInt: + return encodeBigInt, alwaysNotEmpty + case typeRawMessage: + return encodeMarshalerType, isEmptySlice + case typeByteString: + return encodeMarshalerType, isEmptyString + } + if reflect.PtrTo(t).Implements(typeMarshaler) { + return encodeMarshalerType, alwaysNotEmpty + } + if reflect.PtrTo(t).Implements(typeBinaryMarshaler) { + return encodeBinaryMarshalerType, isEmptyBinaryMarshaler + } + switch k { + case reflect.Bool: + return encodeBool, isEmptyBool + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return encodeInt, isEmptyInt + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return encodeUint, isEmptyUint + case reflect.Float32, reflect.Float64: + return encodeFloat, isEmptyFloat + case reflect.String: + return encodeString, isEmptyString + case reflect.Slice, reflect.Array: + if t.Elem().Kind() == reflect.Uint8 { + return encodeByteString, isEmptySlice + } + f, _ := getEncodeFunc(t.Elem()) + if f == nil { + return nil, nil + } + return arrayEncodeFunc{f: f}.encode, isEmptySlice + case reflect.Map: + f := getEncodeMapFunc(t) + if f == nil { + return nil, nil + } + return f, isEmptyMap + case reflect.Struct: + // Get struct's special field "_" tag options + if f, ok := t.FieldByName("_"); ok { + tag := f.Tag.Get("cbor") + if tag != "-" { + if hasToArrayOption(tag) { + return encodeStructToArray, isEmptyStruct + } + } + } + return encodeStruct, isEmptyStruct + case reflect.Interface: + return encodeIntf, isEmptyIntf + } + return nil, nil +} + +func getEncodeIndirectValueFunc(t reflect.Type) encodeFunc { + for t.Kind() == reflect.Ptr { + t = t.Elem() + } + f, _ := getEncodeFunc(t) + if f == nil { + return nil + } + return func(e *encoderBuffer, em *encMode, v reflect.Value) error { + for v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + if v.Kind() == reflect.Ptr && v.IsNil() { + e.Write(cborNil) + return nil + } + return f(e, em, v) + } +} + +func alwaysNotEmpty(_ *encMode, _ reflect.Value) (empty bool, err error) { + return false, nil +} + +func isEmptyBool(_ *encMode, v reflect.Value) (bool, error) { + return !v.Bool(), nil +} + +func isEmptyInt(_ *encMode, v reflect.Value) (bool, error) { + return v.Int() == 0, nil +} + +func isEmptyUint(_ *encMode, v reflect.Value) (bool, error) { + return v.Uint() == 0, nil +} + +func isEmptyFloat(_ *encMode, v reflect.Value) (bool, error) { + return v.Float() == 0.0, nil +} + +func isEmptyString(_ *encMode, v reflect.Value) (bool, error) { + return v.Len() == 0, nil +} + +func isEmptySlice(_ *encMode, v reflect.Value) (bool, error) { + return v.Len() == 0, nil +} + +func isEmptyMap(_ *encMode, v reflect.Value) (bool, error) { + return v.Len() == 0, nil +} + +func isEmptyPtr(_ *encMode, v reflect.Value) (bool, error) { + return v.IsNil(), nil +} + +func isEmptyIntf(_ *encMode, v reflect.Value) (bool, error) { + return v.IsNil(), nil +} + +func isEmptyStruct(em *encMode, v reflect.Value) (bool, error) { + structType, err := getEncodingStructType(v.Type()) + if err != nil { + return false, err + } + + if em.omitEmpty == OmitEmptyGoValue { + return false, nil + } + + if structType.toArray { + return len(structType.fields) == 0, nil + } + + if len(structType.fields) > len(structType.omitEmptyFieldsIdx) { + return false, nil + } + + for _, i := range structType.omitEmptyFieldsIdx { + f := structType.fields[i] + + // Get field value + var fv reflect.Value + if len(f.idx) == 1 { + fv = v.Field(f.idx[0]) + } else { + // Get embedded field value. No error is expected. + fv, _ = getFieldValue(v, f.idx, func(v reflect.Value) (reflect.Value, error) { + // Skip null pointer to embedded struct + return reflect.Value{}, nil + }) + if !fv.IsValid() { + continue + } + } + + empty, err := f.ief(em, fv) + if err != nil { + return false, err + } + if !empty { + return false, nil + } + } + return true, nil +} + +func isEmptyBinaryMarshaler(_ *encMode, v reflect.Value) (bool, error) { + m, ok := v.Interface().(encoding.BinaryMarshaler) + if !ok { + pv := reflect.New(v.Type()) + pv.Elem().Set(v) + m = pv.Interface().(encoding.BinaryMarshaler) + } + data, err := m.MarshalBinary() + if err != nil { + return false, err + } + return len(data) == 0, nil +} + +func cannotFitFloat32(f64 float64) bool { + f32 := float32(f64) + return float64(f32) != f64 +} + +// float32NaNFromReflectValue extracts float32 NaN from reflect.Value while preserving NaN's quiet bit. +func float32NaNFromReflectValue(v reflect.Value) float32 { + // Keith Randall's workaround for issue https://github.com/golang/go/issues/36400 + p := reflect.New(v.Type()) + p.Elem().Set(v) + f32 := p.Convert(reflect.TypeOf((*float32)(nil))).Elem().Interface().(float32) + return f32 +} diff --git a/vendor/github.com/fxamacker/cbor/v2/encode_map.go b/vendor/github.com/fxamacker/cbor/v2/encode_map.go new file mode 100644 index 00000000..9850dc0e --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/encode_map.go @@ -0,0 +1,79 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +//go:build go1.20 + +package cbor + +import ( + "reflect" + "sync" +) + +type mapKeyValueEncodeFunc struct { + kf, ef encodeFunc + kpool, vpool sync.Pool +} + +func (me *mapKeyValueEncodeFunc) encodeKeyValues(e *encoderBuffer, em *encMode, v reflect.Value, kvs []keyValue) error { + trackKeyValueLength := len(kvs) == v.Len() + iterk := me.kpool.Get().(*reflect.Value) + defer func() { + iterk.SetZero() + me.kpool.Put(iterk) + }() + iterv := me.vpool.Get().(*reflect.Value) + defer func() { + iterv.SetZero() + me.vpool.Put(iterv) + }() + iter := v.MapRange() + for i := 0; iter.Next(); i++ { + off := e.Len() + iterk.SetIterKey(iter) + iterv.SetIterValue(iter) + + if err := me.kf(e, em, *iterk); err != nil { + return err + } + if trackKeyValueLength { + kvs[i].keyLen = e.Len() - off + } + + if err := me.ef(e, em, *iterv); err != nil { + return err + } + if trackKeyValueLength { + kvs[i].keyValueLen = e.Len() - off + } + } + + return nil +} + +func getEncodeMapFunc(t reflect.Type) encodeFunc { + kf, _ := getEncodeFunc(t.Key()) + ef, _ := getEncodeFunc(t.Elem()) + if kf == nil || ef == nil { + return nil + } + mkv := &mapKeyValueEncodeFunc{ + kf: kf, + ef: ef, + kpool: sync.Pool{ + New: func() interface{} { + rk := reflect.New(t.Key()).Elem() + return &rk + }, + }, + vpool: sync.Pool{ + New: func() interface{} { + rv := reflect.New(t.Elem()).Elem() + return &rv + }, + }, + } + return mapEncodeFunc{ + e: mkv.encodeKeyValues, + }.encode +} diff --git a/vendor/github.com/fxamacker/cbor/v2/encode_map_go117.go b/vendor/github.com/fxamacker/cbor/v2/encode_map_go117.go new file mode 100644 index 00000000..f9421473 --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/encode_map_go117.go @@ -0,0 +1,51 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +//go:build !go1.20 + +package cbor + +import ( + "reflect" +) + +type mapKeyValueEncodeFunc struct { + kf, ef encodeFunc +} + +func (me *mapKeyValueEncodeFunc) encodeKeyValues(e *encoderBuffer, em *encMode, v reflect.Value, kvs []keyValue) error { + trackKeyValueLength := len(kvs) == v.Len() + + iter := v.MapRange() + for i := 0; iter.Next(); i++ { + off := e.Len() + + if err := me.kf(e, em, iter.Key()); err != nil { + return err + } + if trackKeyValueLength { + kvs[i].keyLen = e.Len() - off + } + + if err := me.ef(e, em, iter.Value()); err != nil { + return err + } + if trackKeyValueLength { + kvs[i].keyValueLen = e.Len() - off + } + } + + return nil +} + +func getEncodeMapFunc(t reflect.Type) encodeFunc { + kf, _ := getEncodeFunc(t.Key()) + ef, _ := getEncodeFunc(t.Elem()) + if kf == nil || ef == nil { + return nil + } + mkv := &mapKeyValueEncodeFunc{kf: kf, ef: ef} + return mapEncodeFunc{ + e: mkv.encodeKeyValues, + }.encode +} diff --git a/vendor/github.com/fxamacker/cbor/v2/simplevalue.go b/vendor/github.com/fxamacker/cbor/v2/simplevalue.go new file mode 100644 index 00000000..6f93f67c --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/simplevalue.go @@ -0,0 +1,69 @@ +package cbor + +import ( + "errors" + "fmt" + "reflect" +) + +// SimpleValue represents CBOR simple value. +// CBOR simple value is: +// - an extension point like CBOR tag. +// - a subset of CBOR major type 7 that isn't floating-point. +// - "identified by a number between 0 and 255, but distinct from that number itself". +// For example, "a simple value 2 is not equivalent to an integer 2" as a CBOR map key. +// +// CBOR simple values identified by 20..23 are: "false", "true" , "null", and "undefined". +// Other CBOR simple values are currently unassigned/reserved by IANA. +type SimpleValue uint8 + +var ( + typeSimpleValue = reflect.TypeOf(SimpleValue(0)) +) + +// MarshalCBOR encodes SimpleValue as CBOR simple value (major type 7). +func (sv SimpleValue) MarshalCBOR() ([]byte, error) { + // RFC 8949 3.3. Floating-Point Numbers and Values with No Content says: + // "An encoder MUST NOT issue two-byte sequences that start with 0xf8 + // (major type 7, additional information 24) and continue with a byte + // less than 0x20 (32 decimal). Such sequences are not well-formed. + // (This implies that an encoder cannot encode false, true, null, or + // undefined in two-byte sequences and that only the one-byte variants + // of these are well-formed; more generally speaking, each simple value + // only has a single representation variant)." + + switch { + case sv <= 23: + return []byte{byte(cborTypePrimitives) | byte(sv)}, nil + + case sv >= 32: + return []byte{byte(cborTypePrimitives) | byte(24), byte(sv)}, nil + + default: + return nil, &UnsupportedValueError{msg: fmt.Sprintf("SimpleValue(%d)", sv)} + } +} + +// UnmarshalCBOR decodes CBOR simple value (major type 7) to SimpleValue. +func (sv *SimpleValue) UnmarshalCBOR(data []byte) error { + if sv == nil { + return errors.New("cbor.SimpleValue: UnmarshalCBOR on nil pointer") + } + + d := decoder{data: data, dm: defaultDecMode} + + typ, ai, val := d.getHead() + + if typ != cborTypePrimitives { + return &UnmarshalTypeError{CBORType: typ.String(), GoType: "SimpleValue"} + } + if ai > 24 { + return &UnmarshalTypeError{CBORType: typ.String(), GoType: "SimpleValue", errorMsg: "not simple values"} + } + + // It is safe to cast val to uint8 here because + // - data is already verified to be well-formed CBOR simple value and + // - val is <= math.MaxUint8. + *sv = SimpleValue(val) + return nil +} diff --git a/vendor/github.com/fxamacker/cbor/v2/stream.go b/vendor/github.com/fxamacker/cbor/v2/stream.go new file mode 100644 index 00000000..02fea43c --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/stream.go @@ -0,0 +1,277 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +package cbor + +import ( + "bytes" + "errors" + "io" + "reflect" +) + +// Decoder reads and decodes CBOR values from io.Reader. +type Decoder struct { + r io.Reader + d decoder + buf []byte + off int // next read offset in buf + bytesRead int +} + +// NewDecoder returns a new decoder that reads and decodes from r using +// the default decoding options. +func NewDecoder(r io.Reader) *Decoder { + return defaultDecMode.NewDecoder(r) +} + +// Decode reads CBOR value and decodes it into the value pointed to by v. +func (dec *Decoder) Decode(v interface{}) error { + _, err := dec.readNext() + if err != nil { + // Return validation error or read error. + return err + } + + dec.d.reset(dec.buf[dec.off:]) + err = dec.d.value(v) + + // Increment dec.off even if decoding err is not nil because + // dec.d.off points to the next CBOR data item if current + // CBOR data item is valid but failed to be decoded into v. + // This allows next CBOR data item to be decoded in next + // call to this function. + dec.off += dec.d.off + dec.bytesRead += dec.d.off + + return err +} + +// Skip skips to the next CBOR data item (if there is any), +// otherwise it returns error such as io.EOF, io.UnexpectedEOF, etc. +func (dec *Decoder) Skip() error { + n, err := dec.readNext() + if err != nil { + // Return validation error or read error. + return err + } + + dec.off += n + dec.bytesRead += n + return nil +} + +// NumBytesRead returns the number of bytes read. +func (dec *Decoder) NumBytesRead() int { + return dec.bytesRead +} + +// Buffered returns a reader for data remaining in Decoder's buffer. +// Returned reader is valid until the next call to Decode or Skip. +func (dec *Decoder) Buffered() io.Reader { + return bytes.NewReader(dec.buf[dec.off:]) +} + +// readNext() reads next CBOR data item from Reader to buffer. +// It returns the size of next CBOR data item. +// It also returns validation error or read error if any. +func (dec *Decoder) readNext() (int, error) { + var readErr error + var validErr error + + for { + // Process any unread data in dec.buf. + if dec.off < len(dec.buf) { + dec.d.reset(dec.buf[dec.off:]) + off := dec.off // Save offset before data validation + validErr = dec.d.wellformed(true) + dec.off = off // Restore offset + + if validErr == nil { + return dec.d.off, nil + } + + if validErr != io.ErrUnexpectedEOF { + return 0, validErr + } + + // Process last read error on io.ErrUnexpectedEOF. + if readErr != nil { + if readErr == io.EOF { + // current CBOR data item is incomplete. + return 0, io.ErrUnexpectedEOF + } + return 0, readErr + } + } + + // More data is needed and there was no read error. + var n int + for n == 0 { + n, readErr = dec.read() + if n == 0 && readErr != nil { + // No more data can be read and read error is encountered. + // At this point, validErr is either nil or io.ErrUnexpectedEOF. + if readErr == io.EOF { + if validErr == io.ErrUnexpectedEOF { + // current CBOR data item is incomplete. + return 0, io.ErrUnexpectedEOF + } + } + return 0, readErr + } + } + + // At this point, dec.buf contains new data from last read (n > 0). + } +} + +// read() reads data from Reader to buffer. +// It returns number of bytes read and any read error encountered. +// Postconditions: +// - dec.buf contains previously unread data and new data. +// - dec.off is 0. +func (dec *Decoder) read() (int, error) { + // Grow buf if needed. + const minRead = 512 + if cap(dec.buf)-len(dec.buf)+dec.off < minRead { + oldUnreadBuf := dec.buf[dec.off:] + dec.buf = make([]byte, len(dec.buf)-dec.off, 2*cap(dec.buf)+minRead) + dec.overwriteBuf(oldUnreadBuf) + } + + // Copy unread data over read data and reset off to 0. + if dec.off > 0 { + dec.overwriteBuf(dec.buf[dec.off:]) + } + + // Read from reader and reslice buf. + n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)]) + dec.buf = dec.buf[0 : len(dec.buf)+n] + return n, err +} + +func (dec *Decoder) overwriteBuf(newBuf []byte) { + n := copy(dec.buf, newBuf) + dec.buf = dec.buf[:n] + dec.off = 0 +} + +// Encoder writes CBOR values to io.Writer. +type Encoder struct { + w io.Writer + em *encMode + indefTypes []cborType +} + +// NewEncoder returns a new encoder that writes to w using the default encoding options. +func NewEncoder(w io.Writer) *Encoder { + return defaultEncMode.NewEncoder(w) +} + +// Encode writes the CBOR encoding of v. +func (enc *Encoder) Encode(v interface{}) error { + if len(enc.indefTypes) > 0 && v != nil { + indefType := enc.indefTypes[len(enc.indefTypes)-1] + if indefType == cborTypeTextString { + k := reflect.TypeOf(v).Kind() + if k != reflect.String { + return errors.New("cbor: cannot encode item type " + k.String() + " for indefinite-length text string") + } + } else if indefType == cborTypeByteString { + t := reflect.TypeOf(v) + k := t.Kind() + if (k != reflect.Array && k != reflect.Slice) || t.Elem().Kind() != reflect.Uint8 { + return errors.New("cbor: cannot encode item type " + k.String() + " for indefinite-length byte string") + } + } + } + + buf := getEncoderBuffer() + + err := encode(buf, enc.em, reflect.ValueOf(v)) + if err == nil { + _, err = enc.w.Write(buf.Bytes()) + } + + putEncoderBuffer(buf) + return err +} + +// StartIndefiniteByteString starts byte string encoding of indefinite length. +// Subsequent calls of (*Encoder).Encode() encodes definite length byte strings +// ("chunks") as one contiguous string until EndIndefinite is called. +func (enc *Encoder) StartIndefiniteByteString() error { + return enc.startIndefinite(cborTypeByteString) +} + +// StartIndefiniteTextString starts text string encoding of indefinite length. +// Subsequent calls of (*Encoder).Encode() encodes definite length text strings +// ("chunks") as one contiguous string until EndIndefinite is called. +func (enc *Encoder) StartIndefiniteTextString() error { + return enc.startIndefinite(cborTypeTextString) +} + +// StartIndefiniteArray starts array encoding of indefinite length. +// Subsequent calls of (*Encoder).Encode() encodes elements of the array +// until EndIndefinite is called. +func (enc *Encoder) StartIndefiniteArray() error { + return enc.startIndefinite(cborTypeArray) +} + +// StartIndefiniteMap starts array encoding of indefinite length. +// Subsequent calls of (*Encoder).Encode() encodes elements of the map +// until EndIndefinite is called. +func (enc *Encoder) StartIndefiniteMap() error { + return enc.startIndefinite(cborTypeMap) +} + +// EndIndefinite closes last opened indefinite length value. +func (enc *Encoder) EndIndefinite() error { + if len(enc.indefTypes) == 0 { + return errors.New("cbor: cannot encode \"break\" code outside indefinite length values") + } + _, err := enc.w.Write([]byte{0xff}) + if err == nil { + enc.indefTypes = enc.indefTypes[:len(enc.indefTypes)-1] + } + return err +} + +var cborIndefHeader = map[cborType][]byte{ + cborTypeByteString: {0x5f}, + cborTypeTextString: {0x7f}, + cborTypeArray: {0x9f}, + cborTypeMap: {0xbf}, +} + +func (enc *Encoder) startIndefinite(typ cborType) error { + if enc.em.indefLength == IndefLengthForbidden { + return &IndefiniteLengthError{typ} + } + _, err := enc.w.Write(cborIndefHeader[typ]) + if err == nil { + enc.indefTypes = append(enc.indefTypes, typ) + } + return err +} + +// RawMessage is a raw encoded CBOR value. +type RawMessage []byte + +// MarshalCBOR returns m or CBOR nil if m is nil. +func (m RawMessage) MarshalCBOR() ([]byte, error) { + if len(m) == 0 { + return cborNil, nil + } + return m, nil +} + +// UnmarshalCBOR creates a copy of data and saves to *m. +func (m *RawMessage) UnmarshalCBOR(data []byte) error { + if m == nil { + return errors.New("cbor.RawMessage: UnmarshalCBOR on nil pointer") + } + *m = append((*m)[0:0], data...) + return nil +} diff --git a/vendor/github.com/fxamacker/cbor/v2/structfields.go b/vendor/github.com/fxamacker/cbor/v2/structfields.go new file mode 100644 index 00000000..23a12bee --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/structfields.go @@ -0,0 +1,252 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +package cbor + +import ( + "reflect" + "sort" + "strings" +) + +type field struct { + name string + nameAsInt int64 // used to decoder to match field name with CBOR int + cborName []byte + cborNameByteString []byte // major type 2 name encoding iff cborName has major type 3 + idx []int + typ reflect.Type + ef encodeFunc + ief isEmptyFunc + typInfo *typeInfo // used to decoder to reuse type info + tagged bool // used to choose dominant field (at the same level tagged fields dominate untagged fields) + omitEmpty bool // used to skip empty field + keyAsInt bool // used to encode/decode field name as int +} + +type fields []*field + +// indexFieldSorter sorts fields by field idx at each level, breaking ties with idx depth. +type indexFieldSorter struct { + fields fields +} + +func (x *indexFieldSorter) Len() int { + return len(x.fields) +} + +func (x *indexFieldSorter) Swap(i, j int) { + x.fields[i], x.fields[j] = x.fields[j], x.fields[i] +} + +func (x *indexFieldSorter) Less(i, j int) bool { + iIdx, jIdx := x.fields[i].idx, x.fields[j].idx + for k := 0; k < len(iIdx) && k < len(jIdx); k++ { + if iIdx[k] != jIdx[k] { + return iIdx[k] < jIdx[k] + } + } + return len(iIdx) <= len(jIdx) +} + +// nameLevelAndTagFieldSorter sorts fields by field name, idx depth, and presence of tag. +type nameLevelAndTagFieldSorter struct { + fields fields +} + +func (x *nameLevelAndTagFieldSorter) Len() int { + return len(x.fields) +} + +func (x *nameLevelAndTagFieldSorter) Swap(i, j int) { + x.fields[i], x.fields[j] = x.fields[j], x.fields[i] +} + +func (x *nameLevelAndTagFieldSorter) Less(i, j int) bool { + fi, fj := x.fields[i], x.fields[j] + if fi.name != fj.name { + return fi.name < fj.name + } + if len(fi.idx) != len(fj.idx) { + return len(fi.idx) < len(fj.idx) + } + if fi.tagged != fj.tagged { + return fi.tagged + } + return i < j // Field i and j have the same name, depth, and tagged status. Nothing else matters. +} + +// getFields returns visible fields of struct type t following visibility rules for JSON encoding. +func getFields(t reflect.Type) (flds fields, structOptions string) { + // Get special field "_" tag options + if f, ok := t.FieldByName("_"); ok { + tag := f.Tag.Get("cbor") + if tag != "-" { + structOptions = tag + } + } + + // nTypes contains next level anonymous fields' types and indexes + // (there can be multiple fields of the same type at the same level) + flds, nTypes := appendFields(t, nil, nil, nil) + + if len(nTypes) > 0 { + + var cTypes map[reflect.Type][][]int // current level anonymous fields' types and indexes + vTypes := map[reflect.Type]bool{t: true} // visited field types at less nested levels + + for len(nTypes) > 0 { + cTypes, nTypes = nTypes, nil + + for t, idx := range cTypes { + // If there are multiple anonymous fields of the same struct type at the same level, all are ignored. + if len(idx) > 1 { + continue + } + + // Anonymous field of the same type at deeper nested level is ignored. + if vTypes[t] { + continue + } + vTypes[t] = true + + flds, nTypes = appendFields(t, idx[0], flds, nTypes) + } + } + } + + sort.Sort(&nameLevelAndTagFieldSorter{flds}) + + // Keep visible fields. + j := 0 // index of next unique field + for i := 0; i < len(flds); { + name := flds[i].name + if i == len(flds)-1 || // last field + name != flds[i+1].name || // field i has unique field name + len(flds[i].idx) < len(flds[i+1].idx) || // field i is at a less nested level than field i+1 + (flds[i].tagged && !flds[i+1].tagged) { // field i is tagged while field i+1 is not + flds[j] = flds[i] + j++ + } + + // Skip fields with the same field name. + for i++; i < len(flds) && name == flds[i].name; i++ { //nolint:revive + } + } + if j != len(flds) { + flds = flds[:j] + } + + // Sort fields by field index + sort.Sort(&indexFieldSorter{flds}) + + return flds, structOptions +} + +// appendFields appends type t's exportable fields to flds and anonymous struct fields to nTypes . +func appendFields(t reflect.Type, idx []int, flds fields, nTypes map[reflect.Type][][]int) (fields, map[reflect.Type][][]int) { + for i := 0; i < t.NumField(); i++ { + f := t.Field(i) + + ft := f.Type + for ft.Kind() == reflect.Ptr { + ft = ft.Elem() + } + + if !isFieldExportable(f, ft.Kind()) { + continue + } + + tag := f.Tag.Get("cbor") + if tag == "" { + tag = f.Tag.Get("json") + } + if tag == "-" { + continue + } + + tagged := len(tag) > 0 + + // Parse field tag options + var tagFieldName string + var omitempty, keyasint bool + for j := 0; len(tag) > 0; j++ { + var token string + idx := strings.IndexByte(tag, ',') + if idx == -1 { + token, tag = tag, "" + } else { + token, tag = tag[:idx], tag[idx+1:] + } + if j == 0 { + tagFieldName = token + } else { + switch token { + case "omitempty": + omitempty = true + case "keyasint": + keyasint = true + } + } + } + + fieldName := tagFieldName + if tagFieldName == "" { + fieldName = f.Name + } + + fIdx := make([]int, len(idx)+1) + copy(fIdx, idx) + fIdx[len(fIdx)-1] = i + + if !f.Anonymous || ft.Kind() != reflect.Struct || len(tagFieldName) > 0 { + flds = append(flds, &field{ + name: fieldName, + idx: fIdx, + typ: f.Type, + omitEmpty: omitempty, + keyAsInt: keyasint, + tagged: tagged}) + } else { + if nTypes == nil { + nTypes = make(map[reflect.Type][][]int) + } + nTypes[ft] = append(nTypes[ft], fIdx) + } + } + + return flds, nTypes +} + +// isFieldExportable returns true if f is an exportable (regular or anonymous) field or +// a nonexportable anonymous field of struct type. +// Nonexportable anonymous field of struct type can contain exportable fields. +func isFieldExportable(f reflect.StructField, fk reflect.Kind) bool { + exportable := f.PkgPath == "" + return exportable || (f.Anonymous && fk == reflect.Struct) +} + +type embeddedFieldNullPtrFunc func(reflect.Value) (reflect.Value, error) + +// getFieldValue returns field value of struct v by index. When encountering null pointer +// to anonymous (embedded) struct field, f is called with the last traversed field value. +func getFieldValue(v reflect.Value, idx []int, f embeddedFieldNullPtrFunc) (fv reflect.Value, err error) { + fv = v + for i, n := range idx { + fv = fv.Field(n) + + if i < len(idx)-1 { + if fv.Kind() == reflect.Ptr && fv.Type().Elem().Kind() == reflect.Struct { + if fv.IsNil() { + // Null pointer to embedded struct field + fv, err = f(fv) + if err != nil || !fv.IsValid() { + return fv, err + } + } + fv = fv.Elem() + } + } + } + return fv, nil +} diff --git a/vendor/github.com/fxamacker/cbor/v2/tag.go b/vendor/github.com/fxamacker/cbor/v2/tag.go new file mode 100644 index 00000000..aefb4d35 --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/tag.go @@ -0,0 +1,297 @@ +package cbor + +import ( + "errors" + "fmt" + "reflect" + "sync" +) + +// Tag represents CBOR tag data, including tag number and unmarshaled tag content. +type Tag struct { + Number uint64 + Content interface{} +} + +// RawTag represents CBOR tag data, including tag number and raw tag content. +// RawTag implements Unmarshaler and Marshaler interfaces. +type RawTag struct { + Number uint64 + Content RawMessage +} + +// UnmarshalCBOR sets *t with tag number and raw tag content copied from data. +func (t *RawTag) UnmarshalCBOR(data []byte) error { + if t == nil { + return errors.New("cbor.RawTag: UnmarshalCBOR on nil pointer") + } + + // Decoding CBOR null and undefined to cbor.RawTag is no-op. + if len(data) == 1 && (data[0] == 0xf6 || data[0] == 0xf7) { + return nil + } + + d := decoder{data: data, dm: defaultDecMode} + + // Unmarshal tag number. + typ, _, num := d.getHead() + if typ != cborTypeTag { + return &UnmarshalTypeError{CBORType: typ.String(), GoType: typeRawTag.String()} + } + t.Number = num + + // Unmarshal tag content. + c := d.data[d.off:] + t.Content = make([]byte, len(c)) + copy(t.Content, c) + return nil +} + +// MarshalCBOR returns CBOR encoding of t. +func (t RawTag) MarshalCBOR() ([]byte, error) { + if t.Number == 0 && len(t.Content) == 0 { + // Marshal uninitialized cbor.RawTag + b := make([]byte, len(cborNil)) + copy(b, cborNil) + return b, nil + } + + e := getEncoderBuffer() + + encodeHead(e, byte(cborTypeTag), t.Number) + + content := t.Content + if len(content) == 0 { + content = cborNil + } + + buf := make([]byte, len(e.Bytes())+len(content)) + n := copy(buf, e.Bytes()) + copy(buf[n:], content) + + putEncoderBuffer(e) + return buf, nil +} + +// DecTagMode specifies how decoder handles tag number. +type DecTagMode int + +const ( + // DecTagIgnored makes decoder ignore tag number (skips if present). + DecTagIgnored DecTagMode = iota + + // DecTagOptional makes decoder verify tag number if it's present. + DecTagOptional + + // DecTagRequired makes decoder verify tag number and tag number must be present. + DecTagRequired + + maxDecTagMode +) + +func (dtm DecTagMode) valid() bool { + return dtm >= 0 && dtm < maxDecTagMode +} + +// EncTagMode specifies how encoder handles tag number. +type EncTagMode int + +const ( + // EncTagNone makes encoder not encode tag number. + EncTagNone EncTagMode = iota + + // EncTagRequired makes encoder encode tag number. + EncTagRequired + + maxEncTagMode +) + +func (etm EncTagMode) valid() bool { + return etm >= 0 && etm < maxEncTagMode +} + +// TagOptions specifies how encoder and decoder handle tag number. +type TagOptions struct { + DecTag DecTagMode + EncTag EncTagMode +} + +// TagSet is an interface to add and remove tag info. It is used by EncMode and DecMode +// to provide CBOR tag support. +type TagSet interface { + // Add adds given tag number(s), content type, and tag options to TagSet. + Add(opts TagOptions, contentType reflect.Type, num uint64, nestedNum ...uint64) error + + // Remove removes given tag content type from TagSet. + Remove(contentType reflect.Type) + + tagProvider +} + +type tagProvider interface { + getTagItemFromType(t reflect.Type) *tagItem + getTypeFromTagNum(num []uint64) reflect.Type +} + +type tagItem struct { + num []uint64 + cborTagNum []byte + contentType reflect.Type + opts TagOptions +} + +func (t *tagItem) equalTagNum(num []uint64) bool { + // Fast path to compare 1 tag number + if len(t.num) == 1 && len(num) == 1 && t.num[0] == num[0] { + return true + } + + if len(t.num) != len(num) { + return false + } + + for i := 0; i < len(t.num); i++ { + if t.num[i] != num[i] { + return false + } + } + + return true +} + +type ( + tagSet map[reflect.Type]*tagItem + + syncTagSet struct { + sync.RWMutex + t tagSet + } +) + +func (t tagSet) getTagItemFromType(typ reflect.Type) *tagItem { + return t[typ] +} + +func (t tagSet) getTypeFromTagNum(num []uint64) reflect.Type { + for typ, tag := range t { + if tag.equalTagNum(num) { + return typ + } + } + return nil +} + +// NewTagSet returns TagSet (safe for concurrency). +func NewTagSet() TagSet { + return &syncTagSet{t: make(map[reflect.Type]*tagItem)} +} + +// Add adds given tag number(s), content type, and tag options to TagSet. +func (t *syncTagSet) Add(opts TagOptions, contentType reflect.Type, num uint64, nestedNum ...uint64) error { + if contentType == nil { + return errors.New("cbor: cannot add nil content type to TagSet") + } + for contentType.Kind() == reflect.Ptr { + contentType = contentType.Elem() + } + tag, err := newTagItem(opts, contentType, num, nestedNum...) + if err != nil { + return err + } + t.Lock() + defer t.Unlock() + for typ, ti := range t.t { + if typ == contentType { + return errors.New("cbor: content type " + contentType.String() + " already exists in TagSet") + } + if ti.equalTagNum(tag.num) { + return fmt.Errorf("cbor: tag number %v already exists in TagSet", tag.num) + } + } + t.t[contentType] = tag + return nil +} + +// Remove removes given tag content type from TagSet. +func (t *syncTagSet) Remove(contentType reflect.Type) { + for contentType.Kind() == reflect.Ptr { + contentType = contentType.Elem() + } + t.Lock() + delete(t.t, contentType) + t.Unlock() +} + +func (t *syncTagSet) getTagItemFromType(typ reflect.Type) *tagItem { + t.RLock() + ti := t.t[typ] + t.RUnlock() + return ti +} + +func (t *syncTagSet) getTypeFromTagNum(num []uint64) reflect.Type { + t.RLock() + rt := t.t.getTypeFromTagNum(num) + t.RUnlock() + return rt +} + +func newTagItem(opts TagOptions, contentType reflect.Type, num uint64, nestedNum ...uint64) (*tagItem, error) { + if opts.DecTag == DecTagIgnored && opts.EncTag == EncTagNone { + return nil, errors.New("cbor: cannot add tag with DecTagIgnored and EncTagNone options to TagSet") + } + if contentType.PkgPath() == "" || contentType.Kind() == reflect.Interface { + return nil, errors.New("cbor: can only add named types to TagSet, got " + contentType.String()) + } + if contentType == typeTime { + return nil, errors.New("cbor: cannot add time.Time to TagSet, use EncOptions.TimeTag and DecOptions.TimeTag instead") + } + if contentType == typeBigInt { + return nil, errors.New("cbor: cannot add big.Int to TagSet, it's built-in and supported automatically") + } + if contentType == typeTag { + return nil, errors.New("cbor: cannot add cbor.Tag to TagSet") + } + if contentType == typeRawTag { + return nil, errors.New("cbor: cannot add cbor.RawTag to TagSet") + } + if num == 0 || num == 1 { + return nil, errors.New("cbor: cannot add tag number 0 or 1 to TagSet, use EncOptions.TimeTag and DecOptions.TimeTag instead") + } + if num == 2 || num == 3 { + return nil, errors.New("cbor: cannot add tag number 2 or 3 to TagSet, it's built-in and supported automatically") + } + if num == selfDescribedCBORTagNum { + return nil, errors.New("cbor: cannot add tag number 55799 to TagSet, it's built-in and ignored automatically") + } + + te := tagItem{num: []uint64{num}, opts: opts, contentType: contentType} + te.num = append(te.num, nestedNum...) + + // Cache encoded tag numbers + e := getEncoderBuffer() + for _, n := range te.num { + encodeHead(e, byte(cborTypeTag), n) + } + te.cborTagNum = make([]byte, e.Len()) + copy(te.cborTagNum, e.Bytes()) + putEncoderBuffer(e) + + return &te, nil +} + +var ( + typeTag = reflect.TypeOf(Tag{}) + typeRawTag = reflect.TypeOf(RawTag{}) +) + +// WrongTagError describes mismatch between CBOR tag and registered tag. +type WrongTagError struct { + RegisteredType reflect.Type + RegisteredTagNum []uint64 + TagNum []uint64 +} + +func (e *WrongTagError) Error() string { + return fmt.Sprintf("cbor: wrong tag number for %s, got %v, expected %v", e.RegisteredType.String(), e.TagNum, e.RegisteredTagNum) +} diff --git a/vendor/github.com/fxamacker/cbor/v2/valid.go b/vendor/github.com/fxamacker/cbor/v2/valid.go new file mode 100644 index 00000000..a5213d06 --- /dev/null +++ b/vendor/github.com/fxamacker/cbor/v2/valid.go @@ -0,0 +1,318 @@ +// Copyright (c) Faye Amacker. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +package cbor + +import ( + "encoding/binary" + "errors" + "io" + "strconv" +) + +// SyntaxError is a description of a CBOR syntax error. +type SyntaxError struct { + msg string +} + +func (e *SyntaxError) Error() string { return e.msg } + +// SemanticError is a description of a CBOR semantic error. +type SemanticError struct { + msg string +} + +func (e *SemanticError) Error() string { return e.msg } + +// MaxNestedLevelError indicates exceeded max nested level of any combination of CBOR arrays/maps/tags. +type MaxNestedLevelError struct { + maxNestedLevels int +} + +func (e *MaxNestedLevelError) Error() string { + return "cbor: exceeded max nested level " + strconv.Itoa(e.maxNestedLevels) +} + +// MaxArrayElementsError indicates exceeded max number of elements for CBOR arrays. +type MaxArrayElementsError struct { + maxArrayElements int +} + +func (e *MaxArrayElementsError) Error() string { + return "cbor: exceeded max number of elements " + strconv.Itoa(e.maxArrayElements) + " for CBOR array" +} + +// MaxMapPairsError indicates exceeded max number of key-value pairs for CBOR maps. +type MaxMapPairsError struct { + maxMapPairs int +} + +func (e *MaxMapPairsError) Error() string { + return "cbor: exceeded max number of key-value pairs " + strconv.Itoa(e.maxMapPairs) + " for CBOR map" +} + +// IndefiniteLengthError indicates found disallowed indefinite length items. +type IndefiniteLengthError struct { + t cborType +} + +func (e *IndefiniteLengthError) Error() string { + return "cbor: indefinite-length " + e.t.String() + " isn't allowed" +} + +// TagsMdError indicates found disallowed CBOR tags. +type TagsMdError struct { +} + +func (e *TagsMdError) Error() string { + return "cbor: CBOR tag isn't allowed" +} + +// ExtraneousDataError indicates found extraneous data following well-formed CBOR data item. +type ExtraneousDataError struct { + numOfBytes int // number of bytes of extraneous data + index int // location of extraneous data +} + +func (e *ExtraneousDataError) Error() string { + return "cbor: " + strconv.Itoa(e.numOfBytes) + " bytes of extraneous data starting at index " + strconv.Itoa(e.index) +} + +// wellformed checks whether the CBOR data item is well-formed. +// allowExtraData indicates if extraneous data is allowed after the CBOR data item. +// - use allowExtraData = true when using Decoder.Decode() +// - use allowExtraData = false when using Unmarshal() +func (d *decoder) wellformed(allowExtraData bool) error { + if len(d.data) == d.off { + return io.EOF + } + _, err := d.wellformedInternal(0) + if err == nil { + if !allowExtraData && d.off != len(d.data) { + err = &ExtraneousDataError{len(d.data) - d.off, d.off} + } + } + return err +} + +// wellformedInternal checks data's well-formedness and returns max depth and error. +func (d *decoder) wellformedInternal(depth int) (int, error) { + t, ai, val, err := d.wellformedHead() + if err != nil { + return 0, err + } + + switch t { + case cborTypeByteString, cborTypeTextString: + if ai == 31 { + if d.dm.indefLength == IndefLengthForbidden { + return 0, &IndefiniteLengthError{t} + } + return d.wellformedIndefiniteString(t, depth) + } + valInt := int(val) + if valInt < 0 { + // Detect integer overflow + return 0, errors.New("cbor: " + t.String() + " length " + strconv.FormatUint(val, 10) + " is too large, causing integer overflow") + } + if len(d.data)-d.off < valInt { // valInt+off may overflow integer + return 0, io.ErrUnexpectedEOF + } + d.off += valInt + case cborTypeArray, cborTypeMap: + depth++ + if depth > d.dm.maxNestedLevels { + return 0, &MaxNestedLevelError{d.dm.maxNestedLevels} + } + + if ai == 31 { + if d.dm.indefLength == IndefLengthForbidden { + return 0, &IndefiniteLengthError{t} + } + return d.wellformedIndefiniteArrayOrMap(t, depth) + } + + valInt := int(val) + if valInt < 0 { + // Detect integer overflow + return 0, errors.New("cbor: " + t.String() + " length " + strconv.FormatUint(val, 10) + " is too large, it would cause integer overflow") + } + + if t == cborTypeArray { + if valInt > d.dm.maxArrayElements { + return 0, &MaxArrayElementsError{d.dm.maxArrayElements} + } + } else { + if valInt > d.dm.maxMapPairs { + return 0, &MaxMapPairsError{d.dm.maxMapPairs} + } + } + + count := 1 + if t == cborTypeMap { + count = 2 + } + maxDepth := depth + for j := 0; j < count; j++ { + for i := 0; i < valInt; i++ { + var dpt int + if dpt, err = d.wellformedInternal(depth); err != nil { + return 0, err + } + if dpt > maxDepth { + maxDepth = dpt // Save max depth + } + } + } + depth = maxDepth + case cborTypeTag: + if d.dm.tagsMd == TagsForbidden { + return 0, &TagsMdError{} + } + + // Scan nested tag numbers to avoid recursion. + for { + if len(d.data) == d.off { // Tag number must be followed by tag content. + return 0, io.ErrUnexpectedEOF + } + if cborType(d.data[d.off]&0xe0) != cborTypeTag { + break + } + if _, _, _, err = d.wellformedHead(); err != nil { + return 0, err + } + depth++ + if depth > d.dm.maxNestedLevels { + return 0, &MaxNestedLevelError{d.dm.maxNestedLevels} + } + } + // Check tag content. + return d.wellformedInternal(depth) + } + return depth, nil +} + +// wellformedIndefiniteString checks indefinite length byte/text string's well-formedness and returns max depth and error. +func (d *decoder) wellformedIndefiniteString(t cborType, depth int) (int, error) { + var err error + for { + if len(d.data) == d.off { + return 0, io.ErrUnexpectedEOF + } + if d.data[d.off] == 0xff { + d.off++ + break + } + // Peek ahead to get next type and indefinite length status. + nt := cborType(d.data[d.off] & 0xe0) + if t != nt { + return 0, &SyntaxError{"cbor: wrong element type " + nt.String() + " for indefinite-length " + t.String()} + } + if (d.data[d.off] & 0x1f) == 31 { + return 0, &SyntaxError{"cbor: indefinite-length " + t.String() + " chunk is not definite-length"} + } + if depth, err = d.wellformedInternal(depth); err != nil { + return 0, err + } + } + return depth, nil +} + +// wellformedIndefiniteArrayOrMap checks indefinite length array/map's well-formedness and returns max depth and error. +func (d *decoder) wellformedIndefiniteArrayOrMap(t cborType, depth int) (int, error) { + var err error + maxDepth := depth + i := 0 + for { + if len(d.data) == d.off { + return 0, io.ErrUnexpectedEOF + } + if d.data[d.off] == 0xff { + d.off++ + break + } + var dpt int + if dpt, err = d.wellformedInternal(depth); err != nil { + return 0, err + } + if dpt > maxDepth { + maxDepth = dpt + } + i++ + if t == cborTypeArray { + if i > d.dm.maxArrayElements { + return 0, &MaxArrayElementsError{d.dm.maxArrayElements} + } + } else { + if i%2 == 0 && i/2 > d.dm.maxMapPairs { + return 0, &MaxMapPairsError{d.dm.maxMapPairs} + } + } + } + if t == cborTypeMap && i%2 == 1 { + return 0, &SyntaxError{"cbor: unexpected \"break\" code"} + } + return maxDepth, nil +} + +func (d *decoder) wellformedHead() (t cborType, ai byte, val uint64, err error) { + dataLen := len(d.data) - d.off + if dataLen == 0 { + return 0, 0, 0, io.ErrUnexpectedEOF + } + + t = cborType(d.data[d.off] & 0xe0) + ai = d.data[d.off] & 0x1f + val = uint64(ai) + d.off++ + + if ai < 24 { + return t, ai, val, nil + } + if ai == 24 { + if dataLen < 2 { + return 0, 0, 0, io.ErrUnexpectedEOF + } + val = uint64(d.data[d.off]) + d.off++ + if t == cborTypePrimitives && val < 32 { + return 0, 0, 0, &SyntaxError{"cbor: invalid simple value " + strconv.Itoa(int(val)) + " for type " + t.String()} + } + return t, ai, val, nil + } + if ai == 25 { + if dataLen < 3 { + return 0, 0, 0, io.ErrUnexpectedEOF + } + val = uint64(binary.BigEndian.Uint16(d.data[d.off : d.off+2])) + d.off += 2 + return t, ai, val, nil + } + if ai == 26 { + if dataLen < 5 { + return 0, 0, 0, io.ErrUnexpectedEOF + } + val = uint64(binary.BigEndian.Uint32(d.data[d.off : d.off+4])) + d.off += 4 + return t, ai, val, nil + } + if ai == 27 { + if dataLen < 9 { + return 0, 0, 0, io.ErrUnexpectedEOF + } + val = binary.BigEndian.Uint64(d.data[d.off : d.off+8]) + d.off += 8 + return t, ai, val, nil + } + if ai == 31 { + switch t { + case cborTypePositiveInt, cborTypeNegativeInt, cborTypeTag: + return 0, 0, 0, &SyntaxError{"cbor: invalid additional information " + strconv.Itoa(int(ai)) + " for type " + t.String()} + case cborTypePrimitives: // 0xff (break code) should not be outside wellformedIndefinite(). + return 0, 0, 0, &SyntaxError{"cbor: unexpected \"break\" code"} + } + return t, ai, val, nil + } + // ai == 28, 29, 30 + return 0, 0, 0, &SyntaxError{"cbor: invalid additional information " + strconv.Itoa(int(ai)) + " for type " + t.String()} +} diff --git a/vendor/github.com/gaissmai/bart/CONTRIBUTING.md b/vendor/github.com/gaissmai/bart/CONTRIBUTING.md new file mode 100644 index 00000000..0b1c4819 --- /dev/null +++ b/vendor/github.com/gaissmai/bart/CONTRIBUTING.md @@ -0,0 +1 @@ +Contributions are welcome, but please open an issue for discussion before sending a pull request. diff --git a/vendor/github.com/gaissmai/bart/LICENSE b/vendor/github.com/gaissmai/bart/LICENSE new file mode 100644 index 00000000..6e65745d --- /dev/null +++ b/vendor/github.com/gaissmai/bart/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Karl Gaissmaier + +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. diff --git a/vendor/github.com/gaissmai/bart/README.md b/vendor/github.com/gaissmai/bart/README.md new file mode 100644 index 00000000..6506cad0 --- /dev/null +++ b/vendor/github.com/gaissmai/bart/README.md @@ -0,0 +1,123 @@ +# package bart + +[![Go Reference](https://pkg.go.dev/badge/github.com/gaissmai/bart.svg)](https://pkg.go.dev/github.com/gaissmai/bart#section-documentation) +![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/gaissmai/bart) +[![CI](https://github.com/gaissmai/bart/actions/workflows/go.yml/badge.svg)](https://github.com/gaissmai/bart/actions/workflows/go.yml) +[![Coverage Status](https://coveralls.io/repos/github/gaissmai/bart/badge.svg)](https://coveralls.io/github/gaissmai/bart) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua) + +## Overview + +`package bart` provides a Balanced-Routing-Table (BART). + +BART is balanced in terms of memory consumption versus +lookup time. + +The lookup time is by a factor of ~2 slower on average as the +routing algorithms ART, SMART, CPE, ... but reduces the memory +consumption by an order of magnitude in comparison. + +BART is a multibit-trie with fixed stride length of 8 bits, +using the _baseIndex_ function from the ART algorithm to +build the complete-binary-tree (CBT) of prefixes for each stride. + +The second key factor is popcount array compression at each stride level +of the CBT prefix tree and backtracking along the CBT in O(k). + +The CBT is implemented as a bitvector, backtracking is just +a matter of fast cache friendly bitmask operations. + +The child array at each stride level is also popcount compressed. + +## API + +The API changes in v0.4.2, 0.5.3, v0.6.3, v0.10.1, v0.11.0 + +```golang + import "github.com/gaissmai/bart" + + type Table[V any] struct { + // Has unexported fields. + } + Table is an IPv4 and IPv6 routing table with payload V. The zero value is + ready to use. + + The Table is safe for concurrent readers but not for concurrent readers + and/or writers. + + func (t *Table[V]) Insert(pfx netip.Prefix, val V) + func (t *Table[V]) Delete(pfx netip.Prefix) + func (t *Table[V]) Get(pfx netip.Prefix) (val V, ok bool) + func (t *Table[V]) Update(pfx netip.Prefix, cb func(val V, ok bool) V) (newVal V) + + func (t *Table[V]) Union(o *Table[V]) + func (t *Table[V]) Clone() *Table[V] + + func (t *Table[V]) Lookup(ip netip.Addr) (val V, ok bool) + + func (t *Table[V]) LookupPrefix(pfx netip.Prefix) (val V, ok bool) + func (t *Table[V]) LookupPrefixLPM(pfx netip.Prefix) (lpm netip.Prefix, val V, ok bool) + func (t *Table[V]) EachLookupPrefix(pfx netip.Prefix, yield func(pfx netip.Prefix, val V) bool) + func (t *Table[V]) EachSubnet(pfx netip.Prefix, yield func(pfx netip.Prefix, val V) bool) + + func (t *Table[V]) OverlapsPrefix(pfx netip.Prefix) bool + + func (t *Table[V]) Overlaps(o *Table[V]) bool + func (t *Table[V]) Overlaps4(o *Table[V]) bool + func (t *Table[V]) Overlaps6(o *Table[V]) bool + + func (t *Table[V]) Size() int + func (t *Table[V]) Size4() int + func (t *Table[V]) Size6() int + + func (t *Table[V]) All(yield func(pfx netip.Prefix, val V) bool) + func (t *Table[V]) All4(yield func(pfx netip.Prefix, val V) bool) + func (t *Table[V]) All6(yield func(pfx netip.Prefix, val V) bool) + + func (t *Table[V]) AllSorted(yield func(pfx netip.Prefix, val V) bool) + func (t *Table[V]) All4Sorted(yield func(pfx netip.Prefix, val V) bool) + func (t *Table[V]) All6Sorted(yield func(pfx netip.Prefix, val V) bool) + + func (t *Table[V]) String() string + func (t *Table[V]) Fprint(w io.Writer) error + func (t *Table[V]) MarshalText() ([]byte, error) + func (t *Table[V]) MarshalJSON() ([]byte, error) + + func (t *Table[V]) DumpList4() []DumpListNode[V] + func (t *Table[V]) DumpList6() []DumpListNode[V] +``` + +## benchmarks + +Please see the extensive [benchmarks](https://github.com/gaissmai/iprbench) comparing `bart` with other IP routing table implementations. + +Just a teaser, LPM lookups against the full Internet routing table with random probes: + +``` +goos: linux +goarch: amd64 +pkg: github.com/gaissmai/bart +cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz + +BenchmarkFullMatchV4/Lookup 24484828 49.03 ns/op +BenchmarkFullMatchV6/Lookup 17098262 70.15 ns/op +BenchmarkFullMissV4/Lookup 24480925 49.15 ns/op +BenchmarkFullMissV6/Lookup 54955310 21.79 ns/op +``` + +## CONTRIBUTION + +Please open an issue for discussion before sending a pull request. + +## CREDIT + +Credits for many inspirations go to the clever guys at tailscale, +to Daniel Lemire for the super-fast bitset package and +to Donald E. Knuth for the **ART** routing algorithm and +all the rest of his *Art* and for keeping important algorithms +in the public domain! + +## LICENSE + +MIT diff --git a/vendor/github.com/gaissmai/bart/base_index.go b/vendor/github.com/gaissmai/bart/base_index.go new file mode 100644 index 00000000..205851a1 --- /dev/null +++ b/vendor/github.com/gaissmai/bart/base_index.go @@ -0,0 +1,621 @@ +// Copyright (c) 2024 Karl Gaissmaier +// SPDX-License-Identifier: MIT + +package bart + +import "cmp" + +// Please read the ART paper ./doc/artlookup.pdf +// to understand the baseIndex algorithm. + +// hostMasks as lookup table +var hostMasks = []uint8{ + 0b1111_1111, // bits == 0 + 0b0111_1111, // bits == 1 + 0b0011_1111, // bits == 2 + 0b0001_1111, // bits == 3 + 0b0000_1111, // bits == 4 + 0b0000_0111, // bits == 5 + 0b0000_0011, // bits == 6 + 0b0000_0001, // bits == 7 + 0b0000_0000, // bits == 8 +} + +func netMask(mask int) uint8 { + return ^hostMasks[uint8(mask)] +} + +const ( + + // baseIndex of the first host route: prefixToBaseIndex(0,8) + firstHostIndex = 0b1_0000_0000 // 256 + + // baseIndex of the last host route: prefixToBaseIndex(255,8) + //nolint:unused + lastHostIndex = 0b1_1111_1111 // 511 +) + +// prefixToBaseIndex, maps a prefix table as a 'complete binary tree'. +// This is the so-called baseIndex a.k.a heapFunc: +func prefixToBaseIndex(octet byte, prefixLen int) uint { + return uint(octet>>(strideLen-prefixLen)) + (1 << prefixLen) +} + +// octetToBaseIndex, just prefixToBaseIndex(octet, 8), a.k.a host routes +// but faster, use it for host routes in Lookup. +func octetToBaseIndex(octet byte) uint { + return uint(octet) + firstHostIndex // just: octet + 256 +} + +// baseIndexToPrefixLen, calc the bits from baseIndex and octect depth +func baseIndexToPrefixLen(baseIdx uint, depth int) int { + _, pfxLen := baseIndexToPrefix(baseIdx) + return depth*strideLen + pfxLen +} + +// hostRoutesByIndex, get range of host routes for this idx. +// +// idx: 72 +// prefix: 32/6 +// lower: 256 + 32 = 288 +// upper: 256 + (32 | 0b0000_0011) = 291 +// +// Use the pre computed lookup table. +// +// func hostRoutesByIndex(idx uint) (uint, uint) { +// octet, bits := baseIndexToPrefix(idx) +// return octetToBaseIndex(octet), octetToBaseIndex(octet | hostMasks[bits]) +// } +func hostRoutesByIndex(idx uint) (uint, uint) { + item := baseIdxLookupTbl[idx] + return uint(item.lower), uint(item.upper) +} + +// baseIndexToPrefix returns the octet and prefix len of baseIdx. +// It's the inverse to prefixToBaseIndex. +// +// Use the pre computed lookup table, bits.LeadingZeros is too slow. +// +// func baseIndexToPrefix(baseIdx uint) (octet byte, pfxLen int) { +// nlz := bits.LeadingZeros(baseIdx) +// pfxLen = strconv.IntSize - nlz - 1 +// octet = (baseIdx & (0xFF >> (8 - pfxLen))) << (8 - pfxLen) +// return octet, pfxLen +// } +func baseIndexToPrefix(baseIdx uint) (octet byte, pfxLen int) { + item := baseIdxLookupTbl[baseIdx] + return item.octet, int(item.bits) +} + +// cmpIndexRank, compare SortFunc to sort indexes in prefix sort order. +func cmpIndexRank(a, b uint) int { + return cmp.Compare(baseIdxLookupTbl[a].rank, baseIdxLookupTbl[b].rank) +} + +// baseIdxLookupTbl +// +// octet, bits, +// host route boundaries, +// prefix sort rank +// +// as lookup table. +var baseIdxLookupTbl = [512]struct { + octet byte + bits int8 + lower uint16 // host route lower bound + upper uint16 // host route upper bound + rank uint16 // prefix sort rank +}{ + {0, -1, 0, 0, 0}, // idx == 0 invalid! + {0, 0, 256, 511, 1}, // idx == 1 + {0, 1, 256, 383, 2}, // idx == 2 + {128, 1, 384, 511, 257}, // idx == 3 + {0, 2, 256, 319, 3}, // idx == 4 + {64, 2, 320, 383, 130}, // idx == 5 + {128, 2, 384, 447, 258}, // idx == 6 + {192, 2, 448, 511, 385}, // idx == 7 + {0, 3, 256, 287, 4}, // idx == 8 + {32, 3, 288, 319, 67}, // idx == 9 + {64, 3, 320, 351, 131}, // idx == 10 + {96, 3, 352, 383, 194}, // idx == 11 + {128, 3, 384, 415, 259}, // idx == 12 + {160, 3, 416, 447, 322}, // idx == 13 + {192, 3, 448, 479, 386}, // idx == 14 + {224, 3, 480, 511, 449}, // idx == 15 + {0, 4, 256, 271, 5}, // idx == 16 + {16, 4, 272, 287, 36}, // idx == 17 + {32, 4, 288, 303, 68}, // idx == 18 + {48, 4, 304, 319, 99}, // idx == 19 + {64, 4, 320, 335, 132}, // idx == 20 + {80, 4, 336, 351, 163}, // idx == 21 + {96, 4, 352, 367, 195}, // idx == 22 + {112, 4, 368, 383, 226}, // idx == 23 + {128, 4, 384, 399, 260}, // idx == 24 + {144, 4, 400, 415, 291}, // idx == 25 + {160, 4, 416, 431, 323}, // idx == 26 + {176, 4, 432, 447, 354}, // idx == 27 + {192, 4, 448, 463, 387}, // idx == 28 + {208, 4, 464, 479, 418}, // idx == 29 + {224, 4, 480, 495, 450}, // idx == 30 + {240, 4, 496, 511, 481}, // idx == 31 + {0, 5, 256, 263, 6}, // idx == 32 + {8, 5, 264, 271, 21}, // idx == 33 + {16, 5, 272, 279, 37}, // idx == 34 + {24, 5, 280, 287, 52}, // idx == 35 + {32, 5, 288, 295, 69}, // idx == 36 + {40, 5, 296, 303, 84}, // idx == 37 + {48, 5, 304, 311, 100}, // idx == 38 + {56, 5, 312, 319, 115}, // idx == 39 + {64, 5, 320, 327, 133}, // idx == 40 + {72, 5, 328, 335, 148}, // idx == 41 + {80, 5, 336, 343, 164}, // idx == 42 + {88, 5, 344, 351, 179}, // idx == 43 + {96, 5, 352, 359, 196}, // idx == 44 + {104, 5, 360, 367, 211}, // idx == 45 + {112, 5, 368, 375, 227}, // idx == 46 + {120, 5, 376, 383, 242}, // idx == 47 + {128, 5, 384, 391, 261}, // idx == 48 + {136, 5, 392, 399, 276}, // idx == 49 + {144, 5, 400, 407, 292}, // idx == 50 + {152, 5, 408, 415, 307}, // idx == 51 + {160, 5, 416, 423, 324}, // idx == 52 + {168, 5, 424, 431, 339}, // idx == 53 + {176, 5, 432, 439, 355}, // idx == 54 + {184, 5, 440, 447, 370}, // idx == 55 + {192, 5, 448, 455, 388}, // idx == 56 + {200, 5, 456, 463, 403}, // idx == 57 + {208, 5, 464, 471, 419}, // idx == 58 + {216, 5, 472, 479, 434}, // idx == 59 + {224, 5, 480, 487, 451}, // idx == 60 + {232, 5, 488, 495, 466}, // idx == 61 + {240, 5, 496, 503, 482}, // idx == 62 + {248, 5, 504, 511, 497}, // idx == 63 + {0, 6, 256, 259, 7}, // idx == 64 + {4, 6, 260, 263, 14}, // idx == 65 + {8, 6, 264, 267, 22}, // idx == 66 + {12, 6, 268, 271, 29}, // idx == 67 + {16, 6, 272, 275, 38}, // idx == 68 + {20, 6, 276, 279, 45}, // idx == 69 + {24, 6, 280, 283, 53}, // idx == 70 + {28, 6, 284, 287, 60}, // idx == 71 + {32, 6, 288, 291, 70}, // idx == 72 + {36, 6, 292, 295, 77}, // idx == 73 + {40, 6, 296, 299, 85}, // idx == 74 + {44, 6, 300, 303, 92}, // idx == 75 + {48, 6, 304, 307, 101}, // idx == 76 + {52, 6, 308, 311, 108}, // idx == 77 + {56, 6, 312, 315, 116}, // idx == 78 + {60, 6, 316, 319, 123}, // idx == 79 + {64, 6, 320, 323, 134}, // idx == 80 + {68, 6, 324, 327, 141}, // idx == 81 + {72, 6, 328, 331, 149}, // idx == 82 + {76, 6, 332, 335, 156}, // idx == 83 + {80, 6, 336, 339, 165}, // idx == 84 + {84, 6, 340, 343, 172}, // idx == 85 + {88, 6, 344, 347, 180}, // idx == 86 + {92, 6, 348, 351, 187}, // idx == 87 + {96, 6, 352, 355, 197}, // idx == 88 + {100, 6, 356, 359, 204}, // idx == 89 + {104, 6, 360, 363, 212}, // idx == 90 + {108, 6, 364, 367, 219}, // idx == 91 + {112, 6, 368, 371, 228}, // idx == 92 + {116, 6, 372, 375, 235}, // idx == 93 + {120, 6, 376, 379, 243}, // idx == 94 + {124, 6, 380, 383, 250}, // idx == 95 + {128, 6, 384, 387, 262}, // idx == 96 + {132, 6, 388, 391, 269}, // idx == 97 + {136, 6, 392, 395, 277}, // idx == 98 + {140, 6, 396, 399, 284}, // idx == 99 + {144, 6, 400, 403, 293}, // idx == 100 + {148, 6, 404, 407, 300}, // idx == 101 + {152, 6, 408, 411, 308}, // idx == 102 + {156, 6, 412, 415, 315}, // idx == 103 + {160, 6, 416, 419, 325}, // idx == 104 + {164, 6, 420, 423, 332}, // idx == 105 + {168, 6, 424, 427, 340}, // idx == 106 + {172, 6, 428, 431, 347}, // idx == 107 + {176, 6, 432, 435, 356}, // idx == 108 + {180, 6, 436, 439, 363}, // idx == 109 + {184, 6, 440, 443, 371}, // idx == 110 + {188, 6, 444, 447, 378}, // idx == 111 + {192, 6, 448, 451, 389}, // idx == 112 + {196, 6, 452, 455, 396}, // idx == 113 + {200, 6, 456, 459, 404}, // idx == 114 + {204, 6, 460, 463, 411}, // idx == 115 + {208, 6, 464, 467, 420}, // idx == 116 + {212, 6, 468, 471, 427}, // idx == 117 + {216, 6, 472, 475, 435}, // idx == 118 + {220, 6, 476, 479, 442}, // idx == 119 + {224, 6, 480, 483, 452}, // idx == 120 + {228, 6, 484, 487, 459}, // idx == 121 + {232, 6, 488, 491, 467}, // idx == 122 + {236, 6, 492, 495, 474}, // idx == 123 + {240, 6, 496, 499, 483}, // idx == 124 + {244, 6, 500, 503, 490}, // idx == 125 + {248, 6, 504, 507, 498}, // idx == 126 + {252, 6, 508, 511, 505}, // idx == 127 + {0, 7, 256, 257, 8}, // idx == 128 + {2, 7, 258, 259, 11}, // idx == 129 + {4, 7, 260, 261, 15}, // idx == 130 + {6, 7, 262, 263, 18}, // idx == 131 + {8, 7, 264, 265, 23}, // idx == 132 + {10, 7, 266, 267, 26}, // idx == 133 + {12, 7, 268, 269, 30}, // idx == 134 + {14, 7, 270, 271, 33}, // idx == 135 + {16, 7, 272, 273, 39}, // idx == 136 + {18, 7, 274, 275, 42}, // idx == 137 + {20, 7, 276, 277, 46}, // idx == 138 + {22, 7, 278, 279, 49}, // idx == 139 + {24, 7, 280, 281, 54}, // idx == 140 + {26, 7, 282, 283, 57}, // idx == 141 + {28, 7, 284, 285, 61}, // idx == 142 + {30, 7, 286, 287, 64}, // idx == 143 + {32, 7, 288, 289, 71}, // idx == 144 + {34, 7, 290, 291, 74}, // idx == 145 + {36, 7, 292, 293, 78}, // idx == 146 + {38, 7, 294, 295, 81}, // idx == 147 + {40, 7, 296, 297, 86}, // idx == 148 + {42, 7, 298, 299, 89}, // idx == 149 + {44, 7, 300, 301, 93}, // idx == 150 + {46, 7, 302, 303, 96}, // idx == 151 + {48, 7, 304, 305, 102}, // idx == 152 + {50, 7, 306, 307, 105}, // idx == 153 + {52, 7, 308, 309, 109}, // idx == 154 + {54, 7, 310, 311, 112}, // idx == 155 + {56, 7, 312, 313, 117}, // idx == 156 + {58, 7, 314, 315, 120}, // idx == 157 + {60, 7, 316, 317, 124}, // idx == 158 + {62, 7, 318, 319, 127}, // idx == 159 + {64, 7, 320, 321, 135}, // idx == 160 + {66, 7, 322, 323, 138}, // idx == 161 + {68, 7, 324, 325, 142}, // idx == 162 + {70, 7, 326, 327, 145}, // idx == 163 + {72, 7, 328, 329, 150}, // idx == 164 + {74, 7, 330, 331, 153}, // idx == 165 + {76, 7, 332, 333, 157}, // idx == 166 + {78, 7, 334, 335, 160}, // idx == 167 + {80, 7, 336, 337, 166}, // idx == 168 + {82, 7, 338, 339, 169}, // idx == 169 + {84, 7, 340, 341, 173}, // idx == 170 + {86, 7, 342, 343, 176}, // idx == 171 + {88, 7, 344, 345, 181}, // idx == 172 + {90, 7, 346, 347, 184}, // idx == 173 + {92, 7, 348, 349, 188}, // idx == 174 + {94, 7, 350, 351, 191}, // idx == 175 + {96, 7, 352, 353, 198}, // idx == 176 + {98, 7, 354, 355, 201}, // idx == 177 + {100, 7, 356, 357, 205}, // idx == 178 + {102, 7, 358, 359, 208}, // idx == 179 + {104, 7, 360, 361, 213}, // idx == 180 + {106, 7, 362, 363, 216}, // idx == 181 + {108, 7, 364, 365, 220}, // idx == 182 + {110, 7, 366, 367, 223}, // idx == 183 + {112, 7, 368, 369, 229}, // idx == 184 + {114, 7, 370, 371, 232}, // idx == 185 + {116, 7, 372, 373, 236}, // idx == 186 + {118, 7, 374, 375, 239}, // idx == 187 + {120, 7, 376, 377, 244}, // idx == 188 + {122, 7, 378, 379, 247}, // idx == 189 + {124, 7, 380, 381, 251}, // idx == 190 + {126, 7, 382, 383, 254}, // idx == 191 + {128, 7, 384, 385, 263}, // idx == 192 + {130, 7, 386, 387, 266}, // idx == 193 + {132, 7, 388, 389, 270}, // idx == 194 + {134, 7, 390, 391, 273}, // idx == 195 + {136, 7, 392, 393, 278}, // idx == 196 + {138, 7, 394, 395, 281}, // idx == 197 + {140, 7, 396, 397, 285}, // idx == 198 + {142, 7, 398, 399, 288}, // idx == 199 + {144, 7, 400, 401, 294}, // idx == 200 + {146, 7, 402, 403, 297}, // idx == 201 + {148, 7, 404, 405, 301}, // idx == 202 + {150, 7, 406, 407, 304}, // idx == 203 + {152, 7, 408, 409, 309}, // idx == 204 + {154, 7, 410, 411, 312}, // idx == 205 + {156, 7, 412, 413, 316}, // idx == 206 + {158, 7, 414, 415, 319}, // idx == 207 + {160, 7, 416, 417, 326}, // idx == 208 + {162, 7, 418, 419, 329}, // idx == 209 + {164, 7, 420, 421, 333}, // idx == 210 + {166, 7, 422, 423, 336}, // idx == 211 + {168, 7, 424, 425, 341}, // idx == 212 + {170, 7, 426, 427, 344}, // idx == 213 + {172, 7, 428, 429, 348}, // idx == 214 + {174, 7, 430, 431, 351}, // idx == 215 + {176, 7, 432, 433, 357}, // idx == 216 + {178, 7, 434, 435, 360}, // idx == 217 + {180, 7, 436, 437, 364}, // idx == 218 + {182, 7, 438, 439, 367}, // idx == 219 + {184, 7, 440, 441, 372}, // idx == 220 + {186, 7, 442, 443, 375}, // idx == 221 + {188, 7, 444, 445, 379}, // idx == 222 + {190, 7, 446, 447, 382}, // idx == 223 + {192, 7, 448, 449, 390}, // idx == 224 + {194, 7, 450, 451, 393}, // idx == 225 + {196, 7, 452, 453, 397}, // idx == 226 + {198, 7, 454, 455, 400}, // idx == 227 + {200, 7, 456, 457, 405}, // idx == 228 + {202, 7, 458, 459, 408}, // idx == 229 + {204, 7, 460, 461, 412}, // idx == 230 + {206, 7, 462, 463, 415}, // idx == 231 + {208, 7, 464, 465, 421}, // idx == 232 + {210, 7, 466, 467, 424}, // idx == 233 + {212, 7, 468, 469, 428}, // idx == 234 + {214, 7, 470, 471, 431}, // idx == 235 + {216, 7, 472, 473, 436}, // idx == 236 + {218, 7, 474, 475, 439}, // idx == 237 + {220, 7, 476, 477, 443}, // idx == 238 + {222, 7, 478, 479, 446}, // idx == 239 + {224, 7, 480, 481, 453}, // idx == 240 + {226, 7, 482, 483, 456}, // idx == 241 + {228, 7, 484, 485, 460}, // idx == 242 + {230, 7, 486, 487, 463}, // idx == 243 + {232, 7, 488, 489, 468}, // idx == 244 + {234, 7, 490, 491, 471}, // idx == 245 + {236, 7, 492, 493, 475}, // idx == 246 + {238, 7, 494, 495, 478}, // idx == 247 + {240, 7, 496, 497, 484}, // idx == 248 + {242, 7, 498, 499, 487}, // idx == 249 + {244, 7, 500, 501, 491}, // idx == 250 + {246, 7, 502, 503, 494}, // idx == 251 + {248, 7, 504, 505, 499}, // idx == 252 + {250, 7, 506, 507, 502}, // idx == 253 + {252, 7, 508, 509, 506}, // idx == 254 + {254, 7, 510, 511, 509}, // idx == 255 + {0, 8, 256, 256, 9}, // idx == 256 -- first host route + {1, 8, 257, 257, 10}, // idx == 257 + {2, 8, 258, 258, 12}, // idx == 258 + {3, 8, 259, 259, 13}, // idx == 259 + {4, 8, 260, 260, 16}, // idx == 260 + {5, 8, 261, 261, 17}, // idx == 261 + {6, 8, 262, 262, 19}, // idx == 262 + {7, 8, 263, 263, 20}, // idx == 263 + {8, 8, 264, 264, 24}, // idx == 264 + {9, 8, 265, 265, 25}, // idx == 265 + {10, 8, 266, 266, 27}, // idx == 266 + {11, 8, 267, 267, 28}, // idx == 267 + {12, 8, 268, 268, 31}, // idx == 268 + {13, 8, 269, 269, 32}, // idx == 269 + {14, 8, 270, 270, 34}, // idx == 270 + {15, 8, 271, 271, 35}, // idx == 271 + {16, 8, 272, 272, 40}, // idx == 272 + {17, 8, 273, 273, 41}, // idx == 273 + {18, 8, 274, 274, 43}, // idx == 274 + {19, 8, 275, 275, 44}, // idx == 275 + {20, 8, 276, 276, 47}, // idx == 276 + {21, 8, 277, 277, 48}, // idx == 277 + {22, 8, 278, 278, 50}, // idx == 278 + {23, 8, 279, 279, 51}, // idx == 279 + {24, 8, 280, 280, 55}, // idx == 280 + {25, 8, 281, 281, 56}, // idx == 281 + {26, 8, 282, 282, 58}, // idx == 282 + {27, 8, 283, 283, 59}, // idx == 283 + {28, 8, 284, 284, 62}, // idx == 284 + {29, 8, 285, 285, 63}, // idx == 285 + {30, 8, 286, 286, 65}, // idx == 286 + {31, 8, 287, 287, 66}, // idx == 287 + {32, 8, 288, 288, 72}, // idx == 288 + {33, 8, 289, 289, 73}, // idx == 289 + {34, 8, 290, 290, 75}, // idx == 290 + {35, 8, 291, 291, 76}, // idx == 291 + {36, 8, 292, 292, 79}, // idx == 292 + {37, 8, 293, 293, 80}, // idx == 293 + {38, 8, 294, 294, 82}, // idx == 294 + {39, 8, 295, 295, 83}, // idx == 295 + {40, 8, 296, 296, 87}, // idx == 296 + {41, 8, 297, 297, 88}, // idx == 297 + {42, 8, 298, 298, 90}, // idx == 298 + {43, 8, 299, 299, 91}, // idx == 299 + {44, 8, 300, 300, 94}, // idx == 300 + {45, 8, 301, 301, 95}, // idx == 301 + {46, 8, 302, 302, 97}, // idx == 302 + {47, 8, 303, 303, 98}, // idx == 303 + {48, 8, 304, 304, 103}, // idx == 304 + {49, 8, 305, 305, 104}, // idx == 305 + {50, 8, 306, 306, 106}, // idx == 306 + {51, 8, 307, 307, 107}, // idx == 307 + {52, 8, 308, 308, 110}, // idx == 308 + {53, 8, 309, 309, 111}, // idx == 309 + {54, 8, 310, 310, 113}, // idx == 310 + {55, 8, 311, 311, 114}, // idx == 311 + {56, 8, 312, 312, 118}, // idx == 312 + {57, 8, 313, 313, 119}, // idx == 313 + {58, 8, 314, 314, 121}, // idx == 314 + {59, 8, 315, 315, 122}, // idx == 315 + {60, 8, 316, 316, 125}, // idx == 316 + {61, 8, 317, 317, 126}, // idx == 317 + {62, 8, 318, 318, 128}, // idx == 318 + {63, 8, 319, 319, 129}, // idx == 319 + {64, 8, 320, 320, 136}, // idx == 320 + {65, 8, 321, 321, 137}, // idx == 321 + {66, 8, 322, 322, 139}, // idx == 322 + {67, 8, 323, 323, 140}, // idx == 323 + {68, 8, 324, 324, 143}, // idx == 324 + {69, 8, 325, 325, 144}, // idx == 325 + {70, 8, 326, 326, 146}, // idx == 326 + {71, 8, 327, 327, 147}, // idx == 327 + {72, 8, 328, 328, 151}, // idx == 328 + {73, 8, 329, 329, 152}, // idx == 329 + {74, 8, 330, 330, 154}, // idx == 330 + {75, 8, 331, 331, 155}, // idx == 331 + {76, 8, 332, 332, 158}, // idx == 332 + {77, 8, 333, 333, 159}, // idx == 333 + {78, 8, 334, 334, 161}, // idx == 334 + {79, 8, 335, 335, 162}, // idx == 335 + {80, 8, 336, 336, 167}, // idx == 336 + {81, 8, 337, 337, 168}, // idx == 337 + {82, 8, 338, 338, 170}, // idx == 338 + {83, 8, 339, 339, 171}, // idx == 339 + {84, 8, 340, 340, 174}, // idx == 340 + {85, 8, 341, 341, 175}, // idx == 341 + {86, 8, 342, 342, 177}, // idx == 342 + {87, 8, 343, 343, 178}, // idx == 343 + {88, 8, 344, 344, 182}, // idx == 344 + {89, 8, 345, 345, 183}, // idx == 345 + {90, 8, 346, 346, 185}, // idx == 346 + {91, 8, 347, 347, 186}, // idx == 347 + {92, 8, 348, 348, 189}, // idx == 348 + {93, 8, 349, 349, 190}, // idx == 349 + {94, 8, 350, 350, 192}, // idx == 350 + {95, 8, 351, 351, 193}, // idx == 351 + {96, 8, 352, 352, 199}, // idx == 352 + {97, 8, 353, 353, 200}, // idx == 353 + {98, 8, 354, 354, 202}, // idx == 354 + {99, 8, 355, 355, 203}, // idx == 355 + {100, 8, 356, 356, 206}, // idx == 356 + {101, 8, 357, 357, 207}, // idx == 357 + {102, 8, 358, 358, 209}, // idx == 358 + {103, 8, 359, 359, 210}, // idx == 359 + {104, 8, 360, 360, 214}, // idx == 360 + {105, 8, 361, 361, 215}, // idx == 361 + {106, 8, 362, 362, 217}, // idx == 362 + {107, 8, 363, 363, 218}, // idx == 363 + {108, 8, 364, 364, 221}, // idx == 364 + {109, 8, 365, 365, 222}, // idx == 365 + {110, 8, 366, 366, 224}, // idx == 366 + {111, 8, 367, 367, 225}, // idx == 367 + {112, 8, 368, 368, 230}, // idx == 368 + {113, 8, 369, 369, 231}, // idx == 369 + {114, 8, 370, 370, 233}, // idx == 370 + {115, 8, 371, 371, 234}, // idx == 371 + {116, 8, 372, 372, 237}, // idx == 372 + {117, 8, 373, 373, 238}, // idx == 373 + {118, 8, 374, 374, 240}, // idx == 374 + {119, 8, 375, 375, 241}, // idx == 375 + {120, 8, 376, 376, 245}, // idx == 376 + {121, 8, 377, 377, 246}, // idx == 377 + {122, 8, 378, 378, 248}, // idx == 378 + {123, 8, 379, 379, 249}, // idx == 379 + {124, 8, 380, 380, 252}, // idx == 380 + {125, 8, 381, 381, 253}, // idx == 381 + {126, 8, 382, 382, 255}, // idx == 382 + {127, 8, 383, 383, 256}, // idx == 383 + {128, 8, 384, 384, 264}, // idx == 384 + {129, 8, 385, 385, 265}, // idx == 385 + {130, 8, 386, 386, 267}, // idx == 386 + {131, 8, 387, 387, 268}, // idx == 387 + {132, 8, 388, 388, 271}, // idx == 388 + {133, 8, 389, 389, 272}, // idx == 389 + {134, 8, 390, 390, 274}, // idx == 390 + {135, 8, 391, 391, 275}, // idx == 391 + {136, 8, 392, 392, 279}, // idx == 392 + {137, 8, 393, 393, 280}, // idx == 393 + {138, 8, 394, 394, 282}, // idx == 394 + {139, 8, 395, 395, 283}, // idx == 395 + {140, 8, 396, 396, 286}, // idx == 396 + {141, 8, 397, 397, 287}, // idx == 397 + {142, 8, 398, 398, 289}, // idx == 398 + {143, 8, 399, 399, 290}, // idx == 399 + {144, 8, 400, 400, 295}, // idx == 400 + {145, 8, 401, 401, 296}, // idx == 401 + {146, 8, 402, 402, 298}, // idx == 402 + {147, 8, 403, 403, 299}, // idx == 403 + {148, 8, 404, 404, 302}, // idx == 404 + {149, 8, 405, 405, 303}, // idx == 405 + {150, 8, 406, 406, 305}, // idx == 406 + {151, 8, 407, 407, 306}, // idx == 407 + {152, 8, 408, 408, 310}, // idx == 408 + {153, 8, 409, 409, 311}, // idx == 409 + {154, 8, 410, 410, 313}, // idx == 410 + {155, 8, 411, 411, 314}, // idx == 411 + {156, 8, 412, 412, 317}, // idx == 412 + {157, 8, 413, 413, 318}, // idx == 413 + {158, 8, 414, 414, 320}, // idx == 414 + {159, 8, 415, 415, 321}, // idx == 415 + {160, 8, 416, 416, 327}, // idx == 416 + {161, 8, 417, 417, 328}, // idx == 417 + {162, 8, 418, 418, 330}, // idx == 418 + {163, 8, 419, 419, 331}, // idx == 419 + {164, 8, 420, 420, 334}, // idx == 420 + {165, 8, 421, 421, 335}, // idx == 421 + {166, 8, 422, 422, 337}, // idx == 422 + {167, 8, 423, 423, 338}, // idx == 423 + {168, 8, 424, 424, 342}, // idx == 424 + {169, 8, 425, 425, 343}, // idx == 425 + {170, 8, 426, 426, 345}, // idx == 426 + {171, 8, 427, 427, 346}, // idx == 427 + {172, 8, 428, 428, 349}, // idx == 428 + {173, 8, 429, 429, 350}, // idx == 429 + {174, 8, 430, 430, 352}, // idx == 430 + {175, 8, 431, 431, 353}, // idx == 431 + {176, 8, 432, 432, 358}, // idx == 432 + {177, 8, 433, 433, 359}, // idx == 433 + {178, 8, 434, 434, 361}, // idx == 434 + {179, 8, 435, 435, 362}, // idx == 435 + {180, 8, 436, 436, 365}, // idx == 436 + {181, 8, 437, 437, 366}, // idx == 437 + {182, 8, 438, 438, 368}, // idx == 438 + {183, 8, 439, 439, 369}, // idx == 439 + {184, 8, 440, 440, 373}, // idx == 440 + {185, 8, 441, 441, 374}, // idx == 441 + {186, 8, 442, 442, 376}, // idx == 442 + {187, 8, 443, 443, 377}, // idx == 443 + {188, 8, 444, 444, 380}, // idx == 444 + {189, 8, 445, 445, 381}, // idx == 445 + {190, 8, 446, 446, 383}, // idx == 446 + {191, 8, 447, 447, 384}, // idx == 447 + {192, 8, 448, 448, 391}, // idx == 448 + {193, 8, 449, 449, 392}, // idx == 449 + {194, 8, 450, 450, 394}, // idx == 450 + {195, 8, 451, 451, 395}, // idx == 451 + {196, 8, 452, 452, 398}, // idx == 452 + {197, 8, 453, 453, 399}, // idx == 453 + {198, 8, 454, 454, 401}, // idx == 454 + {199, 8, 455, 455, 402}, // idx == 455 + {200, 8, 456, 456, 406}, // idx == 456 + {201, 8, 457, 457, 407}, // idx == 457 + {202, 8, 458, 458, 409}, // idx == 458 + {203, 8, 459, 459, 410}, // idx == 459 + {204, 8, 460, 460, 413}, // idx == 460 + {205, 8, 461, 461, 414}, // idx == 461 + {206, 8, 462, 462, 416}, // idx == 462 + {207, 8, 463, 463, 417}, // idx == 463 + {208, 8, 464, 464, 422}, // idx == 464 + {209, 8, 465, 465, 423}, // idx == 465 + {210, 8, 466, 466, 425}, // idx == 466 + {211, 8, 467, 467, 426}, // idx == 467 + {212, 8, 468, 468, 429}, // idx == 468 + {213, 8, 469, 469, 430}, // idx == 469 + {214, 8, 470, 470, 432}, // idx == 470 + {215, 8, 471, 471, 433}, // idx == 471 + {216, 8, 472, 472, 437}, // idx == 472 + {217, 8, 473, 473, 438}, // idx == 473 + {218, 8, 474, 474, 440}, // idx == 474 + {219, 8, 475, 475, 441}, // idx == 475 + {220, 8, 476, 476, 444}, // idx == 476 + {221, 8, 477, 477, 445}, // idx == 477 + {222, 8, 478, 478, 447}, // idx == 478 + {223, 8, 479, 479, 448}, // idx == 479 + {224, 8, 480, 480, 454}, // idx == 480 + {225, 8, 481, 481, 455}, // idx == 481 + {226, 8, 482, 482, 457}, // idx == 482 + {227, 8, 483, 483, 458}, // idx == 483 + {228, 8, 484, 484, 461}, // idx == 484 + {229, 8, 485, 485, 462}, // idx == 485 + {230, 8, 486, 486, 464}, // idx == 486 + {231, 8, 487, 487, 465}, // idx == 487 + {232, 8, 488, 488, 469}, // idx == 488 + {233, 8, 489, 489, 470}, // idx == 489 + {234, 8, 490, 490, 472}, // idx == 490 + {235, 8, 491, 491, 473}, // idx == 491 + {236, 8, 492, 492, 476}, // idx == 492 + {237, 8, 493, 493, 477}, // idx == 493 + {238, 8, 494, 494, 479}, // idx == 494 + {239, 8, 495, 495, 480}, // idx == 495 + {240, 8, 496, 496, 485}, // idx == 496 + {241, 8, 497, 497, 486}, // idx == 497 + {242, 8, 498, 498, 488}, // idx == 498 + {243, 8, 499, 499, 489}, // idx == 499 + {244, 8, 500, 500, 492}, // idx == 500 + {245, 8, 501, 501, 493}, // idx == 501 + {246, 8, 502, 502, 495}, // idx == 502 + {247, 8, 503, 503, 496}, // idx == 503 + {248, 8, 504, 504, 500}, // idx == 504 + {249, 8, 505, 505, 501}, // idx == 505 + {250, 8, 506, 506, 503}, // idx == 506 + {251, 8, 507, 507, 504}, // idx == 507 + {252, 8, 508, 508, 507}, // idx == 508 + {253, 8, 509, 509, 508}, // idx == 509 + {254, 8, 510, 510, 510}, // idx == 510 + {255, 8, 511, 511, 511}, // idx == 511 +} diff --git a/vendor/github.com/gaissmai/bart/dumper.go b/vendor/github.com/gaissmai/bart/dumper.go new file mode 100644 index 00000000..2f7c23df --- /dev/null +++ b/vendor/github.com/gaissmai/bart/dumper.go @@ -0,0 +1,205 @@ +// Copyright (c) 2024 Karl Gaissmaier +// SPDX-License-Identifier: MIT + +package bart + +import ( + "fmt" + "io" + "strconv" + "strings" +) + +type nodeType byte + +const ( + nullNode nodeType = iota // empty node + fullNode // prefixes and children + leafNode // only prefixes + intermediateNode // only children +) + +// ################################################## +// useful during development, debugging and testing +// ################################################## + +// dumpString is just a wrapper for dump. +func (t *Table[V]) dumpString() string { + w := new(strings.Builder) + t.dump(w) + return w.String() +} + +// dump the table structure and all the nodes to w. +// +// Output: +// +// [FULL] depth: 0 path: [] / 0 +// indexs(#6): 1 66 128 133 266 383 +// prefxs(#6): 0/0 8/6 0/7 10/7 10/8 127/8 +// childs(#3): 10 127 192 +// +// .[IMED] depth: 1 path: [10] / 8 +// .childs(#1): 0 +// +// ..[LEAF] depth: 2 path: [10.0] / 16 +// ..indexs(#2): 256 257 +// ..prefxs(#2): 0/8 1/8 +// +// .[IMED] depth: 1 path: [127] / 8 +// .childs(#1): 0 +// +// ..[IMED] depth: 2 path: [127.0] / 16 +// ..childs(#1): 0 +// +// ...[LEAF] depth: 3 path: [127.0.0] / 24 +// ...indexs(#1): 257 +// ...prefxs(#1): 1/8 +// +// ... +func (t *Table[V]) dump(w io.Writer) { + t.init() + + fmt.Fprint(w, "### IPv4:") + t.rootV4.dumpRec(w, zeroPath, 0, true) + + fmt.Fprint(w, "### IPv6:") + t.rootV6.dumpRec(w, zeroPath, 0, false) +} + +// dumpRec, rec-descent the trie. +func (n *node[V]) dumpRec(w io.Writer, path [16]byte, depth int, is4 bool) { + n.dump(w, path, depth, is4) + + // make backing arrays, no heap allocs + addrBackingArray := [maxNodeChildren]uint{} + + // the node may have childs, the rec-descent monster starts + for i, addr := range n.allChildAddrs(addrBackingArray[:]) { + octet := byte(addr) + child := n.children[i] + path[depth] = octet + + child.dumpRec(w, path, depth+1, is4) + } +} + +// dump the node to w. +func (n *node[V]) dump(w io.Writer, path [16]byte, depth int, is4 bool) { + bits := depth * strideLen + indent := strings.Repeat(".", depth) + + // node type with depth and octet path and bits. + fmt.Fprintf(w, "\n%s[%s] depth: %d path: [%s] / %d\n", + indent, n.hasType(), depth, ipStridePath(path, depth, is4), bits) + + if nPfxLen := len(n.prefixes); nPfxLen != 0 { + // make backing arrays, no heap allocs + idxBackingArray := [maxNodePrefixes]uint{} + allIndices := n.allStrideIndexes(idxBackingArray[:]) + + // print the baseIndices for this node. + fmt.Fprintf(w, "%sindexs(#%d): %v\n", indent, nPfxLen, allIndices) + + // print the prefixes for this node + fmt.Fprintf(w, "%sprefxs(#%d):", indent, nPfxLen) + + for _, idx := range allIndices { + octet, bits := baseIndexToPrefix(idx) + fmt.Fprintf(w, " %s/%d", octetFmt(octet, is4), bits) + } + fmt.Fprintln(w) + + // print the values for this node + fmt.Fprintf(w, "%svalues(#%d):", indent, nPfxLen) + + for _, val := range n.prefixes { + fmt.Fprintf(w, " %v", val) + } + fmt.Fprintln(w) + } + + if childs := len(n.children); childs != 0 { + // print the childs for this node + fmt.Fprintf(w, "%schilds(#%d):", indent, childs) + + addrBackingArray := [maxNodeChildren]uint{} + for _, addr := range n.allChildAddrs(addrBackingArray[:]) { + octet := byte(addr) + fmt.Fprintf(w, " %s", octetFmt(octet, is4)) + } + fmt.Fprintln(w) + } +} + +// octetFmt, different format strings for IPv4 and IPv6, decimal versus hex. +func octetFmt(octet byte, is4 bool) string { + if is4 { + return fmt.Sprintf("%d", octet) + } + return fmt.Sprintf("0x%02x", octet) +} + +// ip stride path, different formats for IPv4 and IPv6, dotted decimal or hex. +// +// 127.0.0 +// 2001:0d +func ipStridePath(path [16]byte, depth int, is4 bool) string { + buf := new(strings.Builder) + + if is4 { + for i, b := range path[:depth] { + if i != 0 { + buf.WriteString(".") + } + buf.WriteString(strconv.Itoa(int(b))) + } + return buf.String() + } + + for i, b := range path[:depth] { + if i != 0 && i%2 == 0 { + buf.WriteString(":") + } + buf.WriteString(fmt.Sprintf("%02x", b)) + } + return buf.String() +} + +// String implements Stringer for nodeType. +func (nt nodeType) String() string { + switch nt { + case nullNode: + return "NULL" + case fullNode: + return "FULL" + case leafNode: + return "LEAF" + case intermediateNode: + return "IMED" + } + panic("unreachable") +} + +// hasType returns the nodeType. +func (n *node[V]) hasType() nodeType { + lenPefixes := len(n.prefixes) + lenChilds := len(n.children) + + if lenPefixes == 0 && lenChilds != 0 { + return intermediateNode + } + + if lenPefixes == 0 && lenChilds == 0 { + return nullNode + } + + if lenPefixes != 0 && lenChilds == 0 { + return leafNode + } + + if lenPefixes != 0 && lenChilds != 0 { + return fullNode + } + panic("unreachable") +} diff --git a/vendor/github.com/gaissmai/bart/jsonify.go b/vendor/github.com/gaissmai/bart/jsonify.go new file mode 100644 index 00000000..a8887705 --- /dev/null +++ b/vendor/github.com/gaissmai/bart/jsonify.go @@ -0,0 +1,74 @@ +// Copyright (c) 2024 Karl Gaissmaier +// SPDX-License-Identifier: MIT + +package bart + +import ( + "encoding/json" + "net/netip" + "slices" +) + +// DumpListNode contains CIDR, value and list of subnets (tree childrens). +type DumpListNode[V any] struct { + CIDR netip.Prefix `json:"cidr"` + Value V `json:"value"` + Subnets []DumpListNode[V] `json:"subnets,omitempty"` +} + +// MarshalJSON dumps the table into two sorted lists: for ipv4 and ipv6. +// Every root and subnet is an array, not a map, because the order matters. +func (t *Table[V]) MarshalJSON() ([]byte, error) { + t.init() + + result := struct { + Ipv4 []DumpListNode[V] `json:"ipv4,omitempty"` + Ipv6 []DumpListNode[V] `json:"ipv6,omitempty"` + }{ + Ipv4: t.DumpList4(), + Ipv6: t.DumpList6(), + } + + buf, err := json.Marshal(result) + if err != nil { + return nil, err + } + + return buf, nil +} + +// DumpList4 dumps the ipv4 tree into a list of roots and their subnets. +// It can be used to analyze the tree or build custom json representation. +func (t *Table[V]) DumpList4() []DumpListNode[V] { + t.init() + if t.rootV4 == nil { + return nil + } + return t.rootV4.dumpListRec(0, zeroPath, 0, true) +} + +// DumpList6 dumps the ipv6 tree into a list of roots and their subnets. +// It can be used to analyze the tree or build custom json representation. +func (t *Table[V]) DumpList6() []DumpListNode[V] { + t.init() + if t.rootV6 == nil { + return nil + } + return t.rootV6.dumpListRec(0, zeroPath, 0, false) +} + +func (n *node[V]) dumpListRec(parentIdx uint, path [16]byte, depth int, is4 bool) []DumpListNode[V] { + directKids := n.getKidsRec(parentIdx, path, depth, is4) + slices.SortFunc(directKids, cmpKidByPrefix[V]) + + nodes := make([]DumpListNode[V], 0, len(directKids)) + for _, kid := range directKids { + nodes = append(nodes, DumpListNode[V]{ + CIDR: kid.cidr, + Value: kid.val, + Subnets: kid.n.dumpListRec(kid.idx, kid.path, kid.depth, is4), + }) + } + + return nodes +} diff --git a/vendor/github.com/gaissmai/bart/node.go b/vendor/github.com/gaissmai/bart/node.go new file mode 100644 index 00000000..877edf39 --- /dev/null +++ b/vendor/github.com/gaissmai/bart/node.go @@ -0,0 +1,800 @@ +// Copyright (c) 2024 Karl Gaissmaier +// SPDX-License-Identifier: MIT + +package bart + +import ( + "cmp" + "net/netip" + "slices" + + "github.com/bits-and-blooms/bitset" +) + +const ( + strideLen = 8 // octet + maxTreeDepth = 128 / strideLen // 16 + maxNodeChildren = 1 << strideLen // 256 + maxNodePrefixes = 1 << (strideLen + 1) // 512 +) + +// zero value, used manifold +var zeroPath [16]byte + +// node is a level node in the multibit-trie. +// A node has prefixes and children. +// +// The prefixes form a complete binary tree, see the artlookup.pdf +// paper in the doc folder to understand the data structure. +// +// In contrast to the ART algorithm, popcount-compressed slices are used +// instead of fixed-size arrays. +// +// The array slots are also not pre-allocated as in the ART algorithm, +// but backtracking is used for the longest-prefix-match. +// +// The lookup is then slower by a factor of about 2, but this is +// the intended trade-off to prevent memory consumption from exploding. +type node[V any] struct { + prefixesBitset *bitset.BitSet + childrenBitset *bitset.BitSet + + // popcount compressed slices + prefixes []V + children []*node[V] +} + +// newNode, BitSets have to be initialized. +func newNode[V any]() *node[V] { + return &node[V]{ + prefixesBitset: bitset.New(0), // init BitSet + childrenBitset: bitset.New(0), // init BitSet + } +} + +// isEmpty returns true if node has neither prefixes nor children. +func (n *node[V]) isEmpty() bool { + return len(n.prefixes) == 0 && len(n.children) == 0 +} + +// ################## prefixes ################################ + +// prefixRank, Rank() is the key of the popcount compression algorithm, +// mapping between bitset index and slice index. +func (n *node[V]) prefixRank(baseIdx uint) int { + // adjust offset by one to slice index + return int(n.prefixesBitset.Rank(baseIdx)) - 1 +} + +// insertPrefix adds the route for baseIdx, with value val. +// If the value already exists, overwrite it with val and return false. +func (n *node[V]) insertPrefix(baseIdx uint, val V) (ok bool) { + // prefix exists, overwrite val + if n.prefixesBitset.Test(baseIdx) { + n.prefixes[n.prefixRank(baseIdx)] = val + return false + } + + // new, insert into bitset and slice + n.prefixesBitset.Set(baseIdx) + n.prefixes = slices.Insert(n.prefixes, n.prefixRank(baseIdx), val) + return true +} + +// deletePrefix removes the route octet/prefixLen. +// Returns false if there was no prefix to delete. +func (n *node[V]) deletePrefix(octet byte, prefixLen int) (ok bool) { + baseIdx := prefixToBaseIndex(octet, prefixLen) + + // no route entry + if !n.prefixesBitset.Test(baseIdx) { + return false + } + + rnk := n.prefixRank(baseIdx) + + // delete from slice + n.prefixes = slices.Delete(n.prefixes, rnk, rnk+1) + + // delete from bitset, followed by Compact to reduce memory consumption + n.prefixesBitset.Clear(baseIdx) + n.prefixesBitset.Compact() + + return true +} + +// updatePrefix, update or set the value at prefix via callback. The new value returned +// and a bool wether the prefix was already present in the node. +func (n *node[V]) updatePrefix(octet byte, prefixLen int, cb func(V, bool) V) (newVal V, wasPresent bool) { + // calculate idx once + baseIdx := prefixToBaseIndex(octet, prefixLen) + + var rnk int + + // if prefix is set, get current value + var oldVal V + if wasPresent = n.prefixesBitset.Test(baseIdx); wasPresent { + rnk = n.prefixRank(baseIdx) + oldVal = n.prefixes[rnk] + } + + // callback function to get updated or new value + newVal = cb(oldVal, wasPresent) + + // prefix is already set, update and return value + if wasPresent { + n.prefixes[rnk] = newVal + return + } + + // new prefix, insert into bitset ... + n.prefixesBitset.Set(baseIdx) + + // bitset has changed, recalc rank + rnk = n.prefixRank(baseIdx) + + // ... and insert value into slice + n.prefixes = slices.Insert(n.prefixes, rnk, newVal) + + return +} + +// lpm does a route lookup for idx in the 8-bit (stride) routing table +// at this depth and returns (baseIdx, value, true) if a matching +// longest prefix exists, or ok=false otherwise. +// +// backtracking is fast, it's just a bitset test and, if found, one popcount. +// max steps in backtracking is the stride length. +func (n *node[V]) lpm(idx uint) (baseIdx uint, val V, ok bool) { + for baseIdx = idx; baseIdx > 0; baseIdx >>= 1 { + if n.prefixesBitset.Test(baseIdx) { + // longest prefix match + return baseIdx, n.prefixes[n.prefixRank(baseIdx)], true + } + } + + // not found (on this level) + return 0, val, false +} + +// lpmTest for internal use in overlap tests, just return true or false, no value needed. +func (n *node[V]) lpmTest(baseIdx uint) bool { + for idx := baseIdx; idx > 0; idx >>= 1 { + if n.prefixesBitset.Test(idx) { + return true + } + } + + return false +} + +// getValue for baseIdx. +func (n *node[V]) getValue(baseIdx uint) (val V, ok bool) { + if n.prefixesBitset.Test(baseIdx) { + return n.prefixes[n.prefixRank(baseIdx)], true + } + return +} + +// allStrideIndexes returns all baseIndexes set in this stride node in ascending order. +func (n *node[V]) allStrideIndexes(buffer []uint) []uint { + if len(n.prefixes) > len(buffer) { + panic("logic error, buffer is too small") + } + + _, buffer = n.prefixesBitset.NextSetMany(0, buffer) + return buffer +} + +// ################## children ################################ + +// childRank, Rank() is the key of the popcount compression algorithm, +// mapping between bitset index and slice index. +func (n *node[V]) childRank(octet byte) int { + // adjust offset by one to slice index + return int(n.childrenBitset.Rank(uint(octet))) - 1 +} + +// insertChild, insert the child +func (n *node[V]) insertChild(octet byte, child *node[V]) { + // child exists, overwrite it + if n.childrenBitset.Test(uint(octet)) { + n.children[n.childRank(octet)] = child + return + } + + // new insert into bitset and slice + n.childrenBitset.Set(uint(octet)) + n.children = slices.Insert(n.children, n.childRank(octet), child) +} + +// deleteChild, delete the child at octet. It is valid to delete a non-existent child. +func (n *node[V]) deleteChild(octet byte) { + if !n.childrenBitset.Test(uint(octet)) { + return + } + + rnk := n.childRank(octet) + + // delete from slice + n.children = slices.Delete(n.children, rnk, rnk+1) + + // delete from bitset, followed by Compact to reduce memory consumption + n.childrenBitset.Clear(uint(octet)) + n.childrenBitset.Compact() +} + +// getChild returns the child pointer for octet, or nil if none. +func (n *node[V]) getChild(octet byte) *node[V] { + if !n.childrenBitset.Test(uint(octet)) { + return nil + } + + return n.children[n.childRank(octet)] +} + +// allChildAddrs fills the buffer with the octets of all child nodes in ascending order, +// panics if the buffer isn't big enough. +func (n *node[V]) allChildAddrs(buffer []uint) []uint { + if len(n.children) > len(buffer) { + panic("logic error, buffer is too small") + } + + _, buffer = n.childrenBitset.NextSetMany(0, buffer) + return buffer +} + +// #################### nodes ############################################# + +// eachLookupPrefix does an all prefix match in the 8-bit (stride) routing table +// at this depth and calls yield() for any matching CIDR. +func (n *node[V]) eachLookupPrefix(path [16]byte, depth int, is4 bool, octet byte, bits int, yield func(pfx netip.Prefix, val V) bool) bool { + for idx := prefixToBaseIndex(octet, bits); idx > 0; idx >>= 1 { + if n.prefixesBitset.Test(idx) { + cidr, _ := cidrFromPath(path, depth, is4, idx) + val, _ := n.getValue(idx) + + if !yield(cidr, val) { + // early exit + return false + } + } + } + + return true +} + +// overlapsRec returns true if any IP in the nodes n or o overlaps. +func (n *node[V]) overlapsRec(o *node[V]) bool { + // ############################## + // 1. test if any routes overlaps + // ############################## + + nPfxLen := len(n.prefixes) + oPfxLen := len(o.prefixes) + + if oPfxLen > 0 && nPfxLen > 0 { + + // some prefixes are identical + if n.prefixesBitset.IntersectionCardinality(o.prefixesBitset) > 0 { + return true + } + + var nIdx, oIdx uint + + nOK := nPfxLen > 0 + oOK := oPfxLen > 0 + + // zip, range over n and o at the same time to help chance on its way + for nOK || oOK { + + if nOK { + // does any route in o overlap this prefix from n + if nIdx, nOK = n.prefixesBitset.NextSet(nIdx); nOK { + if o.lpmTest(nIdx) { + return true + } + } + nIdx++ + } + + if oOK { + // does any route in n overlap this prefix from o + if oIdx, oOK = o.prefixesBitset.NextSet(oIdx); oOK { + if n.lpmTest(oIdx) { + return true + } + } + oIdx++ + } + } + } + + // #################################### + // 2. test if routes overlaps any child + // #################################### + + nChildLen := len(n.children) + oChildLen := len(o.children) + + var nAddr, oAddr uint + + nOK := nChildLen > 0 && oPfxLen > 0 // test the childs in n against the routes in o + oOK := oChildLen > 0 && nPfxLen > 0 // test the childs in o against the routes in n + + // zip, range over n and o at the same time to help chance on its way + for nOK || oOK { + + if nOK { + // does any route in o overlap this child from n + if nAddr, nOK = n.childrenBitset.NextSet(nAddr); nOK { + if o.lpmTest(octetToBaseIndex(byte(nAddr))) { + return true + } + } + nAddr++ + } + + if oOK { + // does any route in n overlap this child from o + if oAddr, oOK = o.childrenBitset.NextSet(oAddr); oOK { + if n.lpmTest(octetToBaseIndex(byte(oAddr))) { + return true + } + } + oAddr++ + } + } + + // ################################################################ + // 3. rec-descent call for childs with same octet in nodes n and o + // ################################################################ + + // stop condition, n or o have no childs + if nChildLen == 0 || oChildLen == 0 { + return false + } + + // stop condition, no child with identical octet in n and o + if n.childrenBitset.IntersectionCardinality(o.childrenBitset) == 0 { + return false + } + + // swap the nodes, range over shorter bitset + if nChildLen > oChildLen { + n, o = o, n + } + + addrBackingArray := [maxNodeChildren]uint{} + for i, addr := range n.allChildAddrs(addrBackingArray[:]) { + oChild := o.getChild(byte(addr)) + if oChild == nil { + // no child in o with this octet + continue + } + + // we have the slice index for n + nChild := n.children[i] + + // rec-descent + if nChild.overlapsRec(oChild) { + return true + } + } + + return false +} + +// overlapsPrefix returns true if node overlaps with prefix. +func (n *node[V]) overlapsPrefix(octet byte, pfxLen int) bool { + // ################################################## + // 1. test if any route in this node overlaps prefix? + // ################################################## + + pfxIdx := prefixToBaseIndex(octet, pfxLen) + if n.lpmTest(pfxIdx) { + return true + } + + // ################################################# + // 2. test if prefix overlaps any route in this node + // ################################################# + + // lower/upper boundary for host routes + pfxLower, pfxUpper := hostRoutesByIndex(pfxIdx) + + // increment to 'next' routeIdx for start in bitset search + // since pfxIdx already testet by lpm in other direction + routeIdx := pfxIdx * 2 + var ok bool + for { + if routeIdx, ok = n.prefixesBitset.NextSet(routeIdx); !ok { + break + } + + routeLower, routeUpper := hostRoutesByIndex(routeIdx) + if routeLower >= pfxLower && routeUpper <= pfxUpper { + return true + } + + // next route + routeIdx++ + } + + // ################################################# + // 3. test if prefix overlaps any child in this node + // ################################################# + + // set start octet in bitset search with prefix octet + addr := uint(octet) + for { + if addr, ok = n.childrenBitset.NextSet(addr); !ok { + break + } + + idx := addr + firstHostIndex + if idx >= pfxLower && idx <= pfxUpper { + return true + } + + // next round + addr++ + } + + return false +} + +// eachSubnet calls yield() for any covered CIDR by parent prefix. +func (n *node[V]) eachSubnet(path [16]byte, depth int, is4 bool, parentOctet byte, pfxLen int, yield func(pfx netip.Prefix, val V) bool) bool { + // collect all routes covered by this pfx + // see also algorithm in overlapsPrefix + + // can't use lpm, search prefix has no node + parentIdx := prefixToBaseIndex(parentOctet, pfxLen) + parentLower, parentUpper := hostRoutesByIndex(parentIdx) + + // start bitset search at parentIdx + idx := parentIdx + var ok bool + for { + if idx, ok = n.prefixesBitset.NextSet(idx); !ok { + break + } + + // can't use lpm, search prefix has no node + lower, upper := hostRoutesByIndex(idx) + + // idx is covered by parentIdx? + if lower >= parentLower && upper <= parentUpper { + val, _ := n.getValue(idx) + cidr, _ := cidrFromPath(path, depth, is4, idx) + + if !yield(cidr, val) { + // early exit + return false + } + + } + + idx++ + } + + // collect all children covered + var addr uint + for { + if addr, ok = n.childrenBitset.NextSet(addr); !ok { + break + } + octet := byte(addr) + + // make host route for comparison with lower, upper + idx := octetToBaseIndex(octet) + + // is child covered? + if idx >= parentLower && idx <= parentUpper { + c := n.getChild(octet) + + // add (set) this octet to path + path[depth] = octet + + // all cidrs under this child are covered by pfx + if !c.allRec(path, depth+1, is4, yield) { + // early exit + return false + } + } + + addr++ + } + + return true +} + +// unionRec combines two nodes, changing the receiver node. +// If there are duplicate entries, the value is taken from the other node. +// Count duplicate entries to adjust the t.size struct members. +func (n *node[V]) unionRec(o *node[V]) (duplicates int) { + // make backing arrays, no heap allocs + idxBackingArray := [maxNodePrefixes]uint{} + + // for all prefixes in other node do ... + for _, oIdx := range o.allStrideIndexes(idxBackingArray[:]) { + // insert/overwrite prefix/value from oNode to nNode + oVal, _ := o.getValue(oIdx) + if !n.insertPrefix(oIdx, oVal) { + duplicates++ + } + } + + // make backing arrays, no heap allocs + addrBackingArray := [maxNodeChildren]uint{} + + // for all children in other node do ... + for i, oOctet := range o.allChildAddrs(addrBackingArray[:]) { + octet := byte(oOctet) + + // we know the slice index, faster as o.getChild(octet) + oc := o.children[i] + + // get n child with same octet, + // we don't know the slice index in n.children + nc := n.getChild(octet) + + if nc == nil { + // insert cloned child from oNode into nNode + n.insertChild(octet, oc.cloneRec()) + } else { + // both nodes have child with octet, call union rec-descent + duplicates += nc.unionRec(oc) + } + } + return duplicates +} + +// cloneRec, clones the node recursive. +func (n *node[V]) cloneRec() *node[V] { + c := newNode[V]() + if n.isEmpty() { + return c + } + + c.prefixesBitset = n.prefixesBitset.Clone() // deep + c.prefixes = slices.Clone(n.prefixes) // shallow values + + c.childrenBitset = n.childrenBitset.Clone() // deep + c.children = slices.Clone(n.children) // shallow + + // now clone the children deep + for i, child := range c.children { + c.children[i] = child.cloneRec() + } + + return c +} + +// allRec runs recursive the trie, starting at this node and +// the yield function is called for each route entry with prefix and value. +// If the yield function returns false the recursion ends prematurely and the +// false value is propagated. +// +// The iteration order is not defined, just the simplest and fastest recursive implementation. +func (n *node[V]) allRec(path [16]byte, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool { + // for all prefixes in this node do ... + idxBackingArray := [maxNodePrefixes]uint{} + for _, idx := range n.allStrideIndexes(idxBackingArray[:]) { + val, _ := n.getValue(idx) + cidr, _ := cidrFromPath(path, depth, is4, idx) + + // make the callback for this prefix + if !yield(cidr, val) { + // early exit + return false + } + } + + // for all children in this node do ... + addrBackingArray := [maxNodeChildren]uint{} + for i, addr := range n.allChildAddrs(addrBackingArray[:]) { + child := n.children[i] + path[depth] = byte(addr) + + if !child.allRec(path, depth+1, is4, yield) { + // early exit + return false + } + } + + return true +} + +// allRecSorted runs recursive the trie, starting at node and +// the yield function is called for each route entry with prefix and value. +// If the yield function returns false the recursion ends prematurely and the +// false value is propagated. +// +// The iteration is in prefix sort order, it's a very complex implemenation compared with allRec. +func (n *node[V]) allRecSorted(path [16]byte, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool { + // make backing arrays, no heap allocs + addrBackingArray := [maxNodeChildren]uint{} + idxBackingArray := [maxNodePrefixes]uint{} + + // get slice of all child octets, sorted by addr + childAddrs := n.allChildAddrs(addrBackingArray[:]) + childCursor := 0 + + // get slice of all indexes, sorted by idx + allIndices := n.allStrideIndexes(idxBackingArray[:]) + + // re-sort indexes by prefix in place + slices.SortFunc(allIndices, cmpIndexRank) + + // example for entry with root node: + // + // ▼ + // ├─ 0.0.0.1/32 <-- FOOTNOTE A: child 0 in first node + // ├─ 10.0.0.0/7 <-- FOOTNOTE B: prefix 10/7 in first node + // │ └─ 10.0.0.0/8 <-- FOOTNOTE C: prefix 10/8 in first node + // │ └─ 10.0.0.1/32 <-- FOOTNOTE D: child 10 in first node + // ├─ 127.0.0.0/8 <-- FOOTNOTE E: prefix 127/8 in first node + // └─ 192.168.0.0/16 <-- FOOTNOTE F: child 192 in first node + + // range over all indexes in this node, now in prefix sort order + // FOOTNOTE: B, C, E + for i, idx := range allIndices { + // get the host routes for this index + lower, upper := hostRoutesByIndex(idx) + + // adjust host routes for this idx in case the host routes + // of the following idx overlaps + // FOOTNOTE: B and C have overlaps in host routes + // FOOTNOTE: C, E don't overlap in host routes + // FOOTNOTE: E has no following prefix in this node + if i+1 < len(allIndices) { + lower, upper = adjustHostRoutes(idx, allIndices[i+1]) + } + + // handle childs before the host routes of idx + // FOOTNOTE: A + for j := childCursor; j < len(childAddrs); j++ { + addr := childAddrs[j] + octet := byte(addr) + + if octetToBaseIndex(octet) >= lower { + // lower border of host routes + break + } + + // we know the slice index, faster as n.getChild(octet) + c := n.children[j] + + // add (set) this octet to path + path[depth] = octet + + if !c.allRecSorted(path, depth+1, is4, yield) { + // early exit + return false + } + + childCursor++ + } + + // FOOTNOTE: B, C, F + // now handle prefix for idx + val, _ := n.getValue(idx) + cidr, _ := cidrFromPath(path, depth, is4, idx) + + if !yield(cidr, val) { + // early exit + return false + } + + // handle the children in host routes for this prefix + // FOOTNOTE: D + for j := childCursor; j < len(childAddrs); j++ { + addr := childAddrs[j] + octet := byte(addr) + if octetToBaseIndex(octet) > upper { + // out of host routes + break + } + + // we know the slice index, faster as n.getChild(octet) + c := n.children[j] + + // add (set) this octet to path + path[depth] = octet + + if !c.allRecSorted(path, depth+1, is4, yield) { + // early exit + return false + } + + childCursor++ + } + } + + // FOOTNOTE: F + // handle all the rest of the children + for j := childCursor; j < len(childAddrs); j++ { + addr := childAddrs[j] + octet := byte(addr) + + // we know the slice index, faster as n.getChild(octet) + c := n.children[j] + + // add (set) this octet to path + path[depth] = octet + + if !c.allRecSorted(path, depth+1, is4, yield) { + // early exit + return false + } + } + + return true +} + +// adjustHostRoutes, helper function to adjust the lower, upper bounds of the +// host routes in case the host routes of the next idx overlaps +func adjustHostRoutes(idx, next uint) (lower, upper uint) { + lower, upper = hostRoutesByIndex(idx) + + // get the lower host route border of the next idx + nextLower, _ := hostRoutesByIndex(next) + + // is there an overlap? + switch { + case nextLower == lower: + upper = 0 + + // [------------] idx + // [-----] next + // make host routes for this idx invalid + // + // ][ idx + // [-----]^^^^^^] next + // + // these ^^^^^^ children are handled before next prefix + // + // sorry, I know, it's completely confusing + + case nextLower <= upper: + upper = nextLower - 1 + + // [------------] idx + // [------] next + // + // shrink host routes for this idx + // [----][------] idx, next + // ^ + } + + return lower, upper +} + +// numPrefixesRec, calculate the number of prefixes under n. +func (n *node[V]) numPrefixesRec() int { + size := len(n.prefixes) // this node + for _, c := range n.children { + size += c.numPrefixesRec() + } + return size +} + +// numNodesRec, calculate the number of nodes under n. +func (n *node[V]) numNodesRec() int { + size := 1 // this node + for _, c := range n.children { + size += c.numNodesRec() + } + return size +} + +// cmpPrefix, compare func for prefix sort, +// all cidrs are already normalized +func cmpPrefix(a, b netip.Prefix) int { + if cmp := a.Addr().Compare(b.Addr()); cmp != 0 { + return cmp + } + return cmp.Compare(a.Bits(), b.Bits()) +} diff --git a/vendor/github.com/gaissmai/bart/stringify.go b/vendor/github.com/gaissmai/bart/stringify.go new file mode 100644 index 00000000..c41361aa --- /dev/null +++ b/vendor/github.com/gaissmai/bart/stringify.go @@ -0,0 +1,213 @@ +// Copyright (c) 2024 Karl Gaissmaier +// SPDX-License-Identifier: MIT + +package bart + +import ( + "bytes" + "fmt" + "io" + "net/netip" + "slices" + "strings" +) + +// kid, a node has no path information about its predecessors, +// we collect this during the recursive descent. +// The path/depth/idx is needed to get the CIDR back. +type kid[V any] struct { + // for traversing + n *node[V] + path [16]byte + depth int + idx uint + + // for printing + cidr netip.Prefix + val V +} + +// MarshalText implements the encoding.TextMarshaler interface, +// just a wrapper for [Table.Fprint]. +func (t *Table[V]) MarshalText() ([]byte, error) { + t.init() + w := new(bytes.Buffer) + if err := t.Fprint(w); err != nil { + return nil, err + } + return w.Bytes(), nil +} + +// String returns a hierarchical tree diagram of the ordered CIDRs +// as string, just a wrapper for [Table.Fprint]. +// If Fprint returns an error, String panics. +func (t *Table[V]) String() string { + t.init() + w := new(strings.Builder) + if err := t.Fprint(w); err != nil { + panic(err) + } + return w.String() +} + +// Fprint writes a hierarchical tree diagram of the ordered CIDRs to w. +// If w is nil, Fprint panics. +// +// The order from top to bottom is in ascending order of the prefix address +// and the subtree structure is determined by the CIDRs coverage. +// +// ▼ +// ├─ 10.0.0.0/8 (9.9.9.9) +// │ ├─ 10.0.0.0/24 (8.8.8.8) +// │ └─ 10.0.1.0/24 (10.0.0.0) +// ├─ 127.0.0.0/8 (127.0.0.1) +// │ └─ 127.0.0.1/32 (127.0.0.1) +// ├─ 169.254.0.0/16 (10.0.0.0) +// ├─ 172.16.0.0/12 (8.8.8.8) +// └─ 192.168.0.0/16 (9.9.9.9) +// └─ 192.168.1.0/24 (127.0.0.1) +// ▼ +// └─ ::/0 (2001:db8::1) +// ├─ ::1/128 (::1%lo) +// ├─ 2000::/3 (2001:db8::1) +// │ └─ 2001:db8::/32 (2001:db8::1) +// └─ fe80::/10 (::1%eth0) +func (t *Table[V]) Fprint(w io.Writer) error { + t.init() + + if err := t.fprint(w, true); err != nil { + return err + } + + if err := t.fprint(w, false); err != nil { + return err + } + return nil +} + +// fprint is the version dependent adapter to fprintRec. +func (t *Table[V]) fprint(w io.Writer, is4 bool) error { + n := t.rootNodeByVersion(is4) + if n.isEmpty() { + return nil + } + + if _, err := fmt.Fprint(w, "▼\n"); err != nil { + return err + } + if err := n.fprintRec(w, 0, zeroPath, 0, is4, ""); err != nil { + return err + } + return nil +} + +// fprintRec, the output is a hierarchical CIDR tree starting with parentIdx and byte path. +func (n *node[V]) fprintRec(w io.Writer, parentIdx uint, path [16]byte, depth int, is4 bool, pad string) error { + // get direct childs for this parentIdx ... + directKids := n.getKidsRec(parentIdx, path, depth, is4) + + // sort them by netip.Prefix, not by baseIndex + slices.SortFunc(directKids, cmpKidByPrefix[V]) + + // symbols used in tree + glyphe := "├─ " + spacer := "│ " + + // for all direct kids under this node ... + for i, kid := range directKids { + // ... treat last kid special + if i == len(directKids)-1 { + glyphe = "└─ " + spacer = " " + } + + // print prefix and val, padded with glyphe + if _, err := fmt.Fprintf(w, "%s%s (%v)\n", pad+glyphe, kid.cidr, kid.val); err != nil { + return err + } + + // rec-descent with this prefix as parentIdx. + // hierarchical nested tree view, two rec-descent functions + // work together to spoil the reader. + if err := kid.n.fprintRec(w, kid.idx, kid.path, kid.depth, is4, pad+spacer); err != nil { + return err + } + } + + return nil +} + +// getKidsRec, returns the direct kids below path and parentIdx. +// It's a recursive monster together with printRec, +// you have to know the data structure by heart to understand this function! +// +// See the artlookup.pdf paper in the doc folder, +// the baseIndex function is the key. +func (n *node[V]) getKidsRec(parentIdx uint, path [16]byte, depth int, is4 bool) []kid[V] { + directKids := []kid[V]{} + + // make backing arrays, no heap allocs + idxBackingArray := [maxNodePrefixes]uint{} + for _, idx := range n.allStrideIndexes(idxBackingArray[:]) { + // parent or self, handled alreday in an upper stack frame. + if idx <= parentIdx { + continue + } + + // check if lpmIdx for this idx' parent is equal to parentIdx + lpmIdx, _, _ := n.lpm(idx >> 1) + if lpmIdx == parentIdx { + // idx is directKid + val, _ := n.getValue(idx) + cidr, _ := cidrFromPath(path, depth, is4, idx) + + directKids = append(directKids, kid[V]{n, path, depth, idx, cidr, val}) + } + } + + // the node may have childs, the rec-descent monster starts + addrBackingArray := [maxNodeChildren]uint{} + for i, addr := range n.allChildAddrs(addrBackingArray[:]) { + octet := byte(addr) + // do a longest-prefix-match + lpmIdx, _, _ := n.lpm(octetToBaseIndex(octet)) + if lpmIdx == parentIdx { + c := n.children[i] + path[depth] = octet + + // traverse, rec-descent call with next child node + directKids = append(directKids, c.getKidsRec(0, path, depth+1, is4)...) + } + } + + return directKids +} + +// cidrFromPath, get prefix back from byte path, depth, octet and pfxLen. +func cidrFromPath(path [16]byte, depth int, is4 bool, idx uint) (netip.Prefix, error) { + octet, pfxLen := baseIndexToPrefix(idx) + + // set (partially) masked byte in path at depth + path[depth] = octet + + // make ip addr from octets + var ip netip.Addr + if is4 { + b4 := [4]byte{} + copy(b4[:], path[:4]) + ip = netip.AddrFrom4(b4) + } else { + ip = netip.AddrFrom16(path) + } + + // calc bits with pathLen and pfxLen + bits := depth*strideLen + pfxLen + + // make a normalized prefix from ip/bits + return ip.Prefix(bits) +} + +// cmpKidByPrefix, all prefixes are already normalized (Masked). +func cmpKidByPrefix[V any](a, b kid[V]) int { + return cmpPrefix(a.cidr, b.cidr) +} diff --git a/vendor/github.com/gaissmai/bart/table.go b/vendor/github.com/gaissmai/bart/table.go new file mode 100644 index 00000000..19f2cec4 --- /dev/null +++ b/vendor/github.com/gaissmai/bart/table.go @@ -0,0 +1,821 @@ +// Copyright (c) 2024 Karl Gaissmaier +// SPDX-License-Identifier: MIT + +// package bart provides a Balanced-Routing-Table (BART). +// +// BART is balanced in terms of memory consumption versus +// lookup time. +// +// The lookup time is by a factor of ~2 slower on average as the +// routing algorithms ART, SMART, CPE, ... but reduces the memory +// consumption by an order of magnitude in comparison. +// +// BART is a multibit-trie with fixed stride length of 8 bits, +// using the _baseIndex_ function from the ART algorithm to +// build the complete-binary-tree (CBT) of prefixes for each stride. +// +// The second key factor is popcount array compression at each stride level +// of the CBT prefix tree and backtracking along the CBT in O(k). +// +// The CBT is implemented as a bitvector, backtracking is just +// a matter of fast cache friendly bitmask operations. +// +// The child array at each stride level is also popcount compressed. +package bart + +import ( + "net/netip" + "sync" +) + +// Table is an IPv4 and IPv6 routing table with payload V. +// The zero value is ready to use. +// +// The Table is safe for concurrent readers but not for +// concurrent readers and/or writers. +type Table[V any] struct { + rootV4 *node[V] + rootV6 *node[V] + + size4 int + size6 int + + // BitSets have to be initialized. + initOnce sync.Once +} + +// init BitSets once, so no constructor is needed +func (t *Table[V]) init() { + // upfront nil test, faster than the atomic load in sync.Once.Do + // this makes bulk inserts 5% faster and the table is not safe + // for concurrent writers anyway + if t.rootV6 != nil { + return + } + + t.initOnce.Do(func() { + t.rootV4 = newNode[V]() + t.rootV6 = newNode[V]() + }) +} + +// rootNodeByVersion, select root node for ip version. +func (t *Table[V]) rootNodeByVersion(is4 bool) *node[V] { + if is4 { + return t.rootV4 + } + return t.rootV6 +} + +// Insert adds pfx to the tree, with value val. +// If pfx is already present in the tree, its value is set to val. +func (t *Table[V]) Insert(pfx netip.Prefix, val V) { + t.init() + + if !pfx.IsValid() { + return + } + + // values derived from pfx + ip := pfx.Addr() + is4 := ip.Is4() + bits := pfx.Bits() + + // get the root node of the routing table + n := t.rootNodeByVersion(is4) + + // Do not allocate! + // As16() is inlined, the prefered AsSlice() is too complex for inlining. + // starting with go1.23 we can use AsSlice(), + // see https://github.com/golang/go/issues/56136 + + a16 := ip.As16() + octets := a16[:] + if is4 { + octets = octets[12:] + } + + // 10.0.0.0/8 -> 0 + // 10.12.0.0/15 -> 1 + // 10.12.0.0/16 -> 1 + // 10.12.10.9/32 -> 3 + lastOctetIdx := (bits - 1) / strideLen + + // 10.0.0.0/8 -> 10 + // 10.12.0.0/15 -> 12 + // 10.12.0.0/16 -> 12 + // 10.12.10.9/32 -> 9 + lastOctet := octets[lastOctetIdx] + + // 10.0.0.0/8 -> 8 + // 10.12.0.0/15 -> 7 + // 10.12.0.0/16 -> 8 + // 10.12.10.9/32 -> 8 + lastOctetBits := bits - (lastOctetIdx * strideLen) + + // mask the prefix, this is faster than netip.Prefix.Masked() + lastOctet = lastOctet & netMask(lastOctetBits) + + // find the proper trie node to insert prefix + for _, octet := range octets[:lastOctetIdx] { + // descend down to next trie level + c := n.getChild(octet) + if c == nil { + // create and insert missing intermediate child + c = newNode[V]() + n.insertChild(octet, c) + } + + // proceed with next level + n = c + } + + // insert prefix/val into node + if n.insertPrefix(prefixToBaseIndex(lastOctet, lastOctetBits), val) { + t.sizeUpdate(is4, 1) + } +} + +// Update or set the value at pfx with a callback function. +// The callback function is called with (value, ok) and returns a new value.. +// +// If the pfx does not already exist, it is set with the new value. +func (t *Table[V]) Update(pfx netip.Prefix, cb func(val V, ok bool) V) (newVal V) { + t.init() + if !pfx.IsValid() { + var zero V + return zero + } + + // values derived from pfx + ip := pfx.Addr() + is4 := ip.Is4() + bits := pfx.Bits() + + n := t.rootNodeByVersion(is4) + + // do not allocate + a16 := ip.As16() + octets := a16[:] + if is4 { + octets = octets[12:] + } + + // see comment in Insert() + lastOctetIdx := (bits - 1) / strideLen + lastOctet := octets[lastOctetIdx] + lastOctetBits := bits - (lastOctetIdx * strideLen) + + // mask the prefix + lastOctet = lastOctet & netMask(lastOctetBits) + + // find the proper trie node to update prefix + for _, octet := range octets[:lastOctetIdx] { + // descend down to next trie level + c := n.getChild(octet) + if c == nil { + // create and insert missing intermediate child + c = newNode[V]() + n.insertChild(octet, c) + } + + // proceed with next level + n = c + } + + // update/insert prefix into node + var wasPresent bool + newVal, wasPresent = n.updatePrefix(lastOctet, lastOctetBits, cb) + if !wasPresent { + t.sizeUpdate(is4, 1) + } + + return newVal +} + +// Get returns the associated payload for prefix and true, or false if +// prefix is not set in the routing table. +func (t *Table[V]) Get(pfx netip.Prefix) (val V, ok bool) { + if !pfx.IsValid() { + return + } + + // values derived from pfx + ip := pfx.Addr() + is4 := ip.Is4() + bits := pfx.Bits() + + n := t.rootNodeByVersion(is4) + if n == nil { + return + } + + // do not allocate + a16 := ip.As16() + octets := a16[:] + if is4 { + octets = octets[12:] + } + + // see comment in Insert() + lastOctetIdx := (bits - 1) / strideLen + lastOctet := octets[lastOctetIdx] + lastOctetBits := bits - (lastOctetIdx * strideLen) + + // mask the prefix + lastOctet = lastOctet & netMask(lastOctetBits) + + // find the proper trie node + for _, octet := range octets[:lastOctetIdx] { + c := n.getChild(octet) + if c == nil { + // not found + return + } + n = c + } + return n.getValue(prefixToBaseIndex(lastOctet, lastOctetBits)) +} + +// Delete removes pfx from the tree, pfx does not have to be present. +func (t *Table[V]) Delete(pfx netip.Prefix) { + if !pfx.IsValid() { + return + } + + // values derived from pfx + ip := pfx.Addr() + is4 := ip.Is4() + bits := pfx.Bits() + + n := t.rootNodeByVersion(is4) + if n == nil { + return + } + + // do not allocate + a16 := ip.As16() + octets := a16[:] + if is4 { + octets = octets[12:] + } + + // see comment in Insert() + lastOctetIdx := (bits - 1) / strideLen + lastOctet := octets[lastOctetIdx] + lastOctetBits := bits - (lastOctetIdx * strideLen) + + // mask the prefix + lastOctet = lastOctet & netMask(lastOctetBits) + octets[lastOctetIdx] = lastOctet + + // record path to deleted node + stack := [maxTreeDepth]*node[V]{} + + // run variable as stackPointer, see below + var i int + + // find the trie node + for i = range octets { + // push current node on stack for path recording + stack[i] = n + + if i == lastOctetIdx { + break + } + + // descend down to next level + c := n.getChild(octets[i]) + if c == nil { + return + } + n = c + } + + // try to delete prefix in trie node + if !n.deletePrefix(lastOctet, lastOctetBits) { + // nothing deleted + return + } + t.sizeUpdate(is4, -1) + + // purge dangling nodes after successful deletion + for i > 0 { + if n.isEmpty() { + // purge empty node from parents children + parent := stack[i-1] + parent.deleteChild(octets[i-1]) + } + + // unwind the stack + i-- + n = stack[i] + } +} + +// Lookup does a route lookup (longest prefix match) for IP and +// returns the associated value and true, or false if no route matched. +func (t *Table[V]) Lookup(ip netip.Addr) (val V, ok bool) { + if !ip.IsValid() { + return + } + + is4 := ip.Is4() + + n := t.rootNodeByVersion(is4) + if n == nil { + return + } + + // do not allocate + a16 := ip.As16() + octets := a16[:] + if is4 { + octets = octets[12:] + } + + // stack of the traversed nodes for fast backtracking, if needed + stack := [maxTreeDepth]*node[V]{} + + // run variable, used after for loop + var i int + var octet byte + + // find leaf node + for i, octet = range octets { + // push current node on stack for fast backtracking + stack[i] = n + + // go down in tight loop to leaf node + c := n.getChild(octet) + if c == nil { + break + } + n = c + } + + // start backtracking, unwind the stack + for depth := i; depth >= 0; depth-- { + n = stack[depth] + octet = octets[depth] + + // longest prefix match + // micro benchmarking: skip if node has no prefixes + if len(n.prefixes) != 0 { + if _, val, ok := n.lpm(octetToBaseIndex(octet)); ok { + return val, true + } + } + } + return +} + +// LookupPrefix does a route lookup (longest prefix match) for pfx and +// returns the associated value and true, or false if no route matched. +func (t *Table[V]) LookupPrefix(pfx netip.Prefix) (val V, ok bool) { + _, _, val, ok = t.lpmPrefix(pfx) + return val, ok +} + +// LookupPrefixLPM is similar to [Table.LookupPrefix], +// but it returns the lpm prefix in addition to value,ok. +// +// This method is about 20-30% slower than LookupPrefix and should only +// be used if the matching lpm entry is also required for other reasons. +// +// If LookupPrefixLPM is to be used for IP addresses, +// they must be converted to /32 or /128 prefixes. +func (t *Table[V]) LookupPrefixLPM(pfx netip.Prefix) (lpm netip.Prefix, val V, ok bool) { + depth, baseIdx, val, ok := t.lpmPrefix(pfx) + + if ok { + // calculate the mask from baseIdx and depth + mask := baseIndexToPrefixLen(baseIdx, depth) + + // calculate the lpm from ip and mask + lpm, _ = pfx.Addr().Prefix(mask) + } + + return lpm, val, ok +} + +func (t *Table[V]) lpmPrefix(pfx netip.Prefix) (depth int, baseIdx uint, val V, ok bool) { + if !pfx.IsValid() { + return + } + + // values derived from pfx + ip := pfx.Addr() + is4 := ip.Is4() + bits := pfx.Bits() + + n := t.rootNodeByVersion(is4) + if n == nil { + return + } + + // do not allocate + a16 := ip.As16() + octets := a16[:] + if is4 { + octets = octets[12:] + } + + // see comment in Insert() + lastOctetIdx := (bits - 1) / strideLen + lastOctet := octets[lastOctetIdx] + lastOctetBits := bits - (lastOctetIdx * strideLen) + + // mask the prefix + lastOctet = lastOctet & netMask(lastOctetBits) + octets[lastOctetIdx] = lastOctet + + var i int + var octet byte + + // record path to leaf node + stack := [maxTreeDepth]*node[V]{} + + // find the node + for i, octet = range octets[:lastOctetIdx+1] { + // push current node on stack + stack[i] = n + + // go down in tight loop + c := n.getChild(octet) + if c == nil { + break + } + n = c + } + + // start backtracking, unwind the stack + for depth = i; depth >= 0; depth-- { + n = stack[depth] + octet = octets[depth] + + // longest prefix match + // micro benchmarking: skip if node has no prefixes + if len(n.prefixes) != 0 { + + // only the lastOctet may have a different prefix len + // all others are just host routes + idx := uint(0) + if depth == lastOctetIdx { + idx = prefixToBaseIndex(octet, lastOctetBits) + } else { + idx = octetToBaseIndex(octet) + } + + baseIdx, val, ok = n.lpm(idx) + if ok { + return depth, baseIdx, val, ok + } + } + } + return +} + +// EachLookupPrefix calls yield() for each CIDR covering pfx +// in reverse CIDR sort order, from longest-prefix-match to +// shortest-prefix-match. +// +// If the yield function returns false, the iteration ends prematurely. +func (t *Table[V]) EachLookupPrefix(pfx netip.Prefix, yield func(pfx netip.Prefix, val V) bool) { + if !pfx.IsValid() { + return + } + + // values derived from pfx + ip := pfx.Addr() + is4 := ip.Is4() + bits := pfx.Bits() + + n := t.rootNodeByVersion(is4) + if n == nil { + return + } + + // do not allocate + path := ip.As16() + octets := path[:] + if is4 { + octets = octets[12:] + } + copy(path[:], octets[:]) + + // see comment in Insert() + lastOctetIdx := (bits - 1) / strideLen + lastOctet := octets[lastOctetIdx] + lastOctetBits := bits - (lastOctetIdx * strideLen) + + // mask the prefix + lastOctet = lastOctet & netMask(lastOctetBits) + octets[lastOctetIdx] = lastOctet + + // stack of the traversed nodes for reverse ordering of supernets + stack := [maxTreeDepth]*node[V]{} + + // run variable, used after for loop + var i int + var octet byte + + // find last node + for i, octet = range octets[:lastOctetIdx+1] { + // push current node on stack + stack[i] = n + + // go down in tight loop + c := n.getChild(octet) + if c == nil { + break + } + n = c + } + + // start backtracking, unwind the stack + for depth := i; depth >= 0; depth-- { + n = stack[depth] + + // microbenchmarking + if len(n.prefixes) == 0 { + continue + } + + // only the lastOctet may have a different prefix len + if depth == lastOctetIdx { + if !n.eachLookupPrefix(path, depth, is4, lastOctet, lastOctetBits, yield) { + // early exit + return + } + continue + } + + // all others are just host routes + if !n.eachLookupPrefix(path, depth, is4, octets[depth], strideLen, yield) { + // early exit + return + } + } +} + +// EachSubnet calls yield() for each CIDR covered by pfx. +// If the yield function returns false, the iteration ends prematurely. +// +// The sort order is undefined and you must not rely on it! +func (t *Table[V]) EachSubnet(pfx netip.Prefix, yield func(pfx netip.Prefix, val V) bool) { + if !pfx.IsValid() { + return + } + + // values derived from pfx + ip := pfx.Addr() + is4 := ip.Is4() + bits := pfx.Bits() + + n := t.rootNodeByVersion(is4) + if n == nil { + return + } + + // do not allocate + path := ip.As16() + octets := path[:] + if is4 { + octets = octets[12:] + } + copy(path[:], octets[:]) + + // see comment in Insert() + lastOctetIdx := (bits - 1) / strideLen + lastOctet := octets[lastOctetIdx] + lastOctetBits := bits - (lastOctetIdx * strideLen) + + // mask the prefix + lastOctet = lastOctet & netMask(lastOctetBits) + octets[lastOctetIdx] = lastOctet + + // find the trie node + for i, octet := range octets { + if i == lastOctetIdx { + _ = n.eachSubnet(path, i, is4, lastOctet, lastOctetBits, yield) + return + } + + c := n.getChild(octet) + if c == nil { + break + } + + n = c + } +} + +// OverlapsPrefix reports whether any IP in pfx matches a route in the table. +func (t *Table[V]) OverlapsPrefix(pfx netip.Prefix) bool { + if !pfx.IsValid() { + return false + } + + // values derived from pfx + ip := pfx.Addr() + is4 := ip.Is4() + bits := pfx.Bits() + + // get the root node of the routing table + n := t.rootNodeByVersion(is4) + if n == nil { + return false + } + + // do not allocate + a16 := ip.As16() + octets := a16[:] + if is4 { + octets = octets[12:] + } + + // see comment in Insert() + lastOctetIdx := (bits - 1) / strideLen + lastOctet := octets[lastOctetIdx] + lastOctetBits := bits - (lastOctetIdx * strideLen) + + // mask the prefix + lastOctet = lastOctet & netMask(lastOctetBits) + + for _, octet := range octets[:lastOctetIdx] { + // test if any route overlaps prefix´ so far + if n.lpmTest(octetToBaseIndex(octet)) { + return true + } + + // no overlap so far, go down to next c + c := n.getChild(octet) + if c == nil { + return false + } + n = c + } + + return n.overlapsPrefix(lastOctet, lastOctetBits) +} + +// Overlaps reports whether any IP in the table matches a route in the +// other table. +func (t *Table[V]) Overlaps(o *Table[V]) bool { + t.init() + o.init() + + // t is empty + if t.Size() == 0 { + return false + } + + // o is empty + if o.Size() == 0 { + return false + } + + // at least one v4 is empty + if t.size4 == 0 || o.size4 == 0 { + return t.Overlaps6(o) + } + + // at least one v6 is empty + if t.size6 == 0 || o.size6 == 0 { + return t.Overlaps4(o) + } + + return t.Overlaps4(o) || t.Overlaps6(o) +} + +// Overlaps4 reports whether any IPv4 in the table matches a route in the +// other table. +func (t *Table[V]) Overlaps4(o *Table[V]) bool { + t.init() + o.init() + + return t.rootV4.overlapsRec(o.rootV4) +} + +// Overlaps6 reports whether any IPv6 in the table matches a route in the +// other table. +func (t *Table[V]) Overlaps6(o *Table[V]) bool { + t.init() + o.init() + + return t.rootV6.overlapsRec(o.rootV6) +} + +// Union combines two tables, changing the receiver table. +// If there are duplicate entries, the value is taken from the other table. +func (t *Table[V]) Union(o *Table[V]) { + t.init() + o.init() + + dup4 := t.rootV4.unionRec(o.rootV4) + dup6 := t.rootV6.unionRec(o.rootV6) + + t.size4 += o.size4 - dup4 + t.size6 += o.size6 - dup6 +} + +// Clone returns a copy of the routing table. +// The payloads V are copied using assignment, so this is a shallow clone. +func (t *Table[V]) Clone() *Table[V] { + t.init() + + c := new(Table[V]) + c.init() + + c.rootV4 = t.rootV4.cloneRec() + c.rootV6 = t.rootV6.cloneRec() + + c.size4 = t.size4 + c.size6 = t.size6 + + return c +} + +// All may be used in a for/range loop to iterate +// through all the prefixes. +// The sort order is undefined and you must not rely on it! +// +// Prefixes must not be inserted or deleted during iteration, otherwise +// the behavior is undefined. However, value updates are permitted. +// +// If the yield function returns false, the iteration ends prematurely. +func (t *Table[V]) All(yield func(pfx netip.Prefix, val V) bool) { + t.init() + // respect early exit + _ = t.rootV4.allRec(zeroPath, 0, true, yield) && + t.rootV6.allRec(zeroPath, 0, false, yield) +} + +// All4, like [Table.All] but only for the v4 routing table. +func (t *Table[V]) All4(yield func(pfx netip.Prefix, val V) bool) { + t.init() + t.rootV4.allRec(zeroPath, 0, true, yield) +} + +// All6, like [Table.All] but only for the v6 routing table. +func (t *Table[V]) All6(yield func(pfx netip.Prefix, val V) bool) { + t.init() + t.rootV6.allRec(zeroPath, 0, false, yield) +} + +// AllSorted may be used in a for/range loop to iterate +// through all the prefixes in natural CIDR sort order. +// +// Prefixes must not be inserted or deleted during iteration, otherwise +// the behavior is undefined. However, value updates are permitted. +// +// If the yield function returns false, the iteration ends prematurely. +func (t *Table[V]) AllSorted(yield func(pfx netip.Prefix, val V) bool) { + t.init() + // respect early exit + _ = t.rootV4.allRecSorted(zeroPath, 0, true, yield) && + t.rootV6.allRecSorted(zeroPath, 0, false, yield) +} + +// All4Sorted, like [Table.AllSorted] but only for the v4 routing table. +func (t *Table[V]) All4Sorted(yield func(pfx netip.Prefix, val V) bool) { + t.init() + t.rootV4.allRecSorted(zeroPath, 0, true, yield) +} + +// All6Sorted, like [Table.AllSorted] but only for the v6 routing table. +func (t *Table[V]) All6Sorted(yield func(pfx netip.Prefix, val V) bool) { + t.init() + t.rootV6.allRecSorted(zeroPath, 0, false, yield) +} + +func (t *Table[V]) sizeUpdate(is4 bool, n int) { + switch is4 { + case true: + t.size4 += n + case false: + t.size6 += n + } +} + +// Size returns the prefix count. +func (t *Table[V]) Size() int { + return t.size4 + t.size6 +} + +// Size4 returns the IPv4 prefix count. +func (t *Table[V]) Size4() int { + return t.size4 +} + +// Size6 returns the IPv6 prefix count. +func (t *Table[V]) Size6() int { + return t.size6 +} + +// nodes, calculates the IPv4 and IPv6 nodes and returns the sum. +func (t *Table[V]) nodes() int { + t.init() + return t.rootV4.numNodesRec() + t.rootV6.numNodesRec() +} diff --git a/vendor/github.com/go-json-experiment/json/AUTHORS b/vendor/github.com/go-json-experiment/json/AUTHORS new file mode 100644 index 00000000..2b00ddba --- /dev/null +++ b/vendor/github.com/go-json-experiment/json/AUTHORS @@ -0,0 +1,3 @@ +# This source code refers to The Go Authors for copyright purposes. +# The master list of authors is in the main Go distribution, +# visible at https://tip.golang.org/AUTHORS. diff --git a/vendor/github.com/go-json-experiment/json/CONTRIBUTORS b/vendor/github.com/go-json-experiment/json/CONTRIBUTORS new file mode 100644 index 00000000..1fbd3e97 --- /dev/null +++ b/vendor/github.com/go-json-experiment/json/CONTRIBUTORS @@ -0,0 +1,3 @@ +# This source code was written by the Go contributors. +# The master list of contributors is in the main Go distribution, +# visible at https://tip.golang.org/CONTRIBUTORS. diff --git a/vendor/github.com/go-json-experiment/json/LICENSE b/vendor/github.com/go-json-experiment/json/LICENSE new file mode 100644 index 00000000..24412730 --- /dev/null +++ b/vendor/github.com/go-json-experiment/json/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2020 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/go-json-experiment/json/README.md b/vendor/github.com/go-json-experiment/json/README.md new file mode 100644 index 00000000..243e2af4 --- /dev/null +++ b/vendor/github.com/go-json-experiment/json/README.md @@ -0,0 +1,177 @@ +# JSON Serialization (v2) + +[![GoDev](https://img.shields.io/static/v1?label=godev&message=reference&color=00add8)](https://pkg.go.dev/github.com/go-json-experiment/json) +[![Build Status](https://github.com/go-json-experiment/json/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/go-json-experiment/json/actions) + +This module hosts an experimental implementation of v2 `encoding/json`. +The API is unstable and breaking changes will regularly be made. +Do not depend on this in publicly available modules. + +Any commits that make breaking API or behavior changes will be marked +with the string "WARNING: " near the top of the commit message. +It is your responsibility to inspect the list of commit changes +when upgrading the module. Not all breaking changes will lead to build failures. + +A [Discussion about including this package in Go as `encoding/json/v2`](https://github.com/golang/go/discussions/63397) has been started on the Go Github project on 2023-10-05. Please provide your feedback there. + +## Goals and objectives + +* **Mostly backwards compatible:** If possible, v2 should aim to be _mostly_ +compatible with v1 in terms of both API and default behavior to ease migration. +For example, the `Marshal` and `Unmarshal` functions are the most widely used +declarations in the v1 package. It seems sensible for equivalent functionality +in v2 to be named the same and have a mostly compatible signature. +Behaviorally, we should aim for 95% to 99% backwards compatibility. +We do not aim for 100% compatibility since we want the freedom to break +certain behaviors that are now considered to have been a mistake. +We may provide options that can bring the v2 implementation to 100% compatibility, +but it will not be the default. + +* **More flexible:** There is a +[long list of feature requests](https://github.com/golang/go/issues?q=is%3Aissue+is%3Aopen+encoding%2Fjson+in%3Atitle). +We should aim to provide the most flexible features that addresses most usages. +We do not want to over fit the v2 API to handle every possible use case. +Ideally, the features provided should be orthogonal in nature such that +any combination of features results in as few surprising edge cases as possible. + +* **More performant:** JSON serialization is widely used and any bit of extra +performance gains will be greatly appreciated. Some rarely used behaviors of v1 +may be dropped in favor of better performance. For example, +despite `Encoder` and `Decoder` operating on an `io.Writer` and `io.Reader`, +they do not operate in a truly streaming manner, +leading to a loss in performance. The v2 implementation should aim to be truly +streaming by default (see [#33714](https://golang.org/issue/33714)). + +* **Easy to use (hard to misuse):** The v2 API should aim to make +the common case easy and the less common case at least possible. +The API should avoid behavior that goes contrary to user expectation, +which may result in subtle bugs (see [#36225](https://golang.org/issue/36225)). + +* **v1 and v2 maintainability:** Since the v1 implementation must stay forever, +it would be beneficial if v1 could be implemented under the hood with v2, +allowing for less maintenance burden in the future. This probably implies that +behavioral changes in v2 relative to v1 need to be exposed as options. + +* **Avoid unsafe:** Standard library packages generally avoid the use of +package `unsafe` even if it could provide a performance boost. +We aim to preserve this property. + +## Expectations + +While this module aims to possibly be the v2 implementation of `encoding/json`, +there is no guarantee that this outcome will occur. As with any major change +to the Go standard library, this will eventually go through the +[Go proposal process](https://github.com/golang/proposal#readme). +At the present moment, this is still in the design and experimentation phase +and is not ready for a formal proposal. + +There are several possible outcomes from this experiment: +1. We determine that a v2 `encoding/json` would not provide sufficient benefit +over the existing v1 `encoding/json` package. Thus, we abandon this effort. +2. We propose a v2 `encoding/json` design, but it is rejected in favor of some +other design that is considered superior. +3. We propose a v2 `encoding/json` design, but rather than adding an entirely +new v2 `encoding/json` package, we decide to merge its functionality into +the existing v1 `encoding/json` package. +4. We propose a v2 `encoding/json` design and it is accepted, resulting in +its addition to the standard library. +5. Some other unforeseen outcome (among the infinite number of possibilities). + +## Development + +This module is primarily developed by +[@dsnet](https://github.com/dsnet), +[@mvdan](https://github.com/mvdan), and +[@johanbrandhorst](https://github.com/johanbrandhorst) +with feedback provided by +[@rogpeppe](https://github.com/rogpeppe), +[@ChrisHines](https://github.com/ChrisHines), and +[@rsc](https://github.com/rsc). + +Discussion about semantics occur semi-regularly, where a +[record of past meetings can be found here](https://docs.google.com/document/d/1rovrOTd-wTawGMPPlPuKhwXaYBg9VszTXR9AQQL5LfI/edit?usp=sharing). + +## Design overview + +This package aims to provide a clean separation between syntax and semantics. +Syntax deals with the structural representation of JSON (as specified in +[RFC 4627](https://tools.ietf.org/html/rfc4627), +[RFC 7159](https://tools.ietf.org/html/rfc7159), +[RFC 7493](https://tools.ietf.org/html/rfc7493), +[RFC 8259](https://tools.ietf.org/html/rfc8259), and +[RFC 8785](https://tools.ietf.org/html/rfc8785)). +Semantics deals with the meaning of syntactic data as usable application data. + +The `Encoder` and `Decoder` types are streaming tokenizers concerned with the +packing or parsing of JSON data. They operate on `Token` and `Value` types +which represent the common data structures that are representable in JSON. +`Encoder` and `Decoder` do not aim to provide any interpretation of the data. + +Functions like `Marshal`, `MarshalWrite`, `MarshalEncode`, `Unmarshal`, +`UnmarshalRead`, and `UnmarshalDecode` provide semantic meaning by correlating +any arbitrary Go type with some JSON representation of that type (as stored in +data types like `[]byte`, `io.Writer`, `io.Reader`, `Encoder`, or `Decoder`). + +![API overview](api.png) + +This diagram provides a high-level overview of the v2 `json` and `jsontext` packages. +Purple blocks represent types, while blue blocks represent functions or methods. +The arrows and their direction represent the approximate flow of data. +The bottom half of the diagram contains functionality that is only concerned +with syntax (implemented by the `jsontext` package), +while the upper half contains functionality that assigns +semantic meaning to syntactic data handled by the bottom half +(as implemented by the v2 `json` package). + +In contrast to v1 `encoding/json`, options are represented as separate types +rather than being setter methods on the `Encoder` or `Decoder` types. +Some options affects JSON serialization at the syntactic layer, +while others affect it at the semantic layer. +Some options only affect JSON when decoding, +while others affect JSON while encoding. + +## Behavior changes + +The v2 `json` package changes the default behavior of `Marshal` and `Unmarshal` +relative to the v1 `json` package to be more sensible. +Some of these behavior changes have options and workarounds to opt into +behavior similar to what v1 provided. + +This table shows an overview of the changes: + +| v1 | v2 | Details | +| -- | -- | ------- | +| JSON object members are unmarshaled into a Go struct using a **case-insensitive name match**. | JSON object members are unmarshaled into a Go struct using a **case-sensitive name match**. | [CaseSensitivity](/diff_test.go#:~:text=TestCaseSensitivity) | +| When marshaling a Go struct, a struct field marked as `omitempty` is omitted if **the field value is an empty Go value**, which is defined as false, 0, a nil pointer, a nil interface value, and any empty array, slice, map, or string. | When marshaling a Go struct, a struct field marked as `omitempty` is omitted if **the field value would encode as an empty JSON value**, which is defined as a JSON null, or an empty JSON string, object, or array. | [OmitEmptyOption](/diff_test.go#:~:text=TestOmitEmptyOption) | +| The `string` option **does affect** Go bools. | The `string` option **does not affect** Go bools. | [StringOption](/diff_test.go#:~:text=TestStringOption) | +| The `string` option **does not recursively affect** sub-values of the Go field value. | The `string` option **does recursively affect** sub-values of the Go field value. | [StringOption](/diff_test.go#:~:text=TestStringOption) | +| The `string` option **sometimes accepts** a JSON null escaped within a JSON string. | The `string` option **never accepts** a JSON null escaped within a JSON string. | [StringOption](/diff_test.go#:~:text=TestStringOption) | +| A nil Go slice is marshaled as a **JSON null**. | A nil Go slice is marshaled as an **empty JSON array**. | [NilSlicesAndMaps](/diff_test.go#:~:text=TestNilSlicesAndMaps) | +| A nil Go map is marshaled as a **JSON null**. | A nil Go map is marshaled as an **empty JSON object**. | [NilSlicesAndMaps](/diff_test.go#:~:text=TestNilSlicesAndMaps) | +| A Go array may be unmarshaled from a **JSON array of any length**. | A Go array must be unmarshaled from a **JSON array of the same length**. | [Arrays](/diff_test.go#:~:text=Arrays) | +| A Go byte array is represented as a **JSON array of JSON numbers**. | A Go byte array is represented as a **Base64-encoded JSON string**. | [ByteArrays](/diff_test.go#:~:text=TestByteArrays) | +| `MarshalJSON` and `UnmarshalJSON` methods declared on a pointer receiver are **inconsistently called**. | `MarshalJSON` and `UnmarshalJSON` methods declared on a pointer receiver are **consistently called**. | [PointerReceiver](/diff_test.go#:~:text=TestPointerReceiver) | +| A Go map is marshaled in a **deterministic order**. | A Go map is marshaled in a **non-deterministic order**. | [MapDeterminism](/diff_test.go#:~:text=TestMapDeterminism) | +| JSON strings are encoded **with HTML-specific characters being escaped**. | JSON strings are encoded **without any characters being escaped** (unless necessary). | [EscapeHTML](/diff_test.go#:~:text=TestEscapeHTML) | +| When marshaling, invalid UTF-8 within a Go string **are silently replaced**. | When marshaling, invalid UTF-8 within a Go string **results in an error**. | [InvalidUTF8](/diff_test.go#:~:text=TestInvalidUTF8) | +| When unmarshaling, invalid UTF-8 within a JSON string **are silently replaced**. | When unmarshaling, invalid UTF-8 within a JSON string **results in an error**. | [InvalidUTF8](/diff_test.go#:~:text=TestInvalidUTF8) | +| When marshaling, **an error does not occur** if the output JSON value contains objects with duplicate names. | When marshaling, **an error does occur** if the output JSON value contains objects with duplicate names. | [DuplicateNames](/diff_test.go#:~:text=TestDuplicateNames) | +| When unmarshaling, **an error does not occur** if the input JSON value contains objects with duplicate names. | When unmarshaling, **an error does occur** if the input JSON value contains objects with duplicate names. | [DuplicateNames](/diff_test.go#:~:text=TestDuplicateNames) | +| Unmarshaling a JSON null into a non-empty Go value **inconsistently clears the value or does nothing**. | Unmarshaling a JSON null into a non-empty Go value **always clears the value**. | [MergeNull](/diff_test.go#:~:text=TestMergeNull) | +| Unmarshaling a JSON value into a non-empty Go value **follows inconsistent and bizarre behavior**. | Unmarshaling a JSON value into a non-empty Go value **always merges if the input is an object, and otherwise replaces**. | [MergeComposite](/diff_test.go#:~:text=TestMergeComposite) | +| A `time.Duration` is represented as a **JSON number containing the decimal number of nanoseconds**. | A `time.Duration` is represented as a **JSON string containing the formatted duration (e.g., "1h2m3.456s")**. | [TimeDurations](/diff_test.go#:~:text=TestTimeDurations) | +| Unmarshaling a JSON number into a Go float beyond its representation **results in an error**. | Unmarshaling a JSON number into a Go float beyond its representation **uses the closest representable value (e.g., ±`math.MaxFloat`)**. | [MaxFloats](/diff_test.go#:~:text=TestMaxFloats) | +| A Go struct with only unexported fields **can be serialized**. | A Go struct with only unexported fields **cannot be serialized**. | [EmptyStructs](/diff_test.go#:~:text=TestEmptyStructs) | +| A Go struct that embeds an unexported struct type **can sometimes be serialized**. | A Go struct that embeds an unexported struct type **cannot be serialized**. | [EmbedUnexported](/diff_test.go#:~:text=TestEmbedUnexported) | + +See [diff_test.go](/diff_test.go) for details about every change. + +## Performance + +One of the goals of the v2 module is to be more performant than v1, +but not at the expense of correctness. +In general, v2 is at performance parity with v1 for marshaling, +but dramatically faster for unmarshaling. + +See https://github.com/go-json-experiment/jsonbench for benchmarks +comparing v2 with v1 and a number of other popular JSON implementations. diff --git a/vendor/github.com/go-json-experiment/json/api.png b/vendor/github.com/go-json-experiment/json/api.png new file mode 100644 index 0000000000000000000000000000000000000000..778b4dbf2fece2c5bce273b7524c920b13d8e73c GIT binary patch literal 154576 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%0Ax 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�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