diff --git a/.gitignore b/.gitignore index 98de01f6a..93937ecf0 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,8 @@ tags src/golang.org/x/tools/ src/github.com/kisielk/ src/golang.org/x/sync/ + +# Devbox local development environment +devbox.json +devbox.lock +.devbox/ diff --git a/jobs/gorouter/spec b/jobs/gorouter/spec index 8e7a93cf2..5ecdd67c2 100644 --- a/jobs/gorouter/spec +++ b/jobs/gorouter/spec @@ -160,6 +160,8 @@ properties: none - Gorouter will not request client certificates in TLS handshakes, and will ignore them if presented. Incompatible with `forwarded_client_cert: forward` or `sanitize_set`. request - Gorouter will request client certificates in TLS handshakes, and will validate them when presented, but will not require them. require - Gorouter will fail a TLS handshake if the client does not provide a certificate signed by a CA it trusts. Select this option if your load balancer terminates TLS and does not require client certificates, and the load balancer provides a compatible client certificate of its own to Gorouter in an independent TLS handshake. This option may also be selected for Isolation Segments when Gorouter is the first point of TLS termination. Many clients of CF platform APIs do not present client certificates in TLS handshakes, so the first point of TLS termination for requests to the system domain must not require them. This option has no effect on the HTTP listener; to disable HTTP support set `disable_http: true`. + + Note: This property applies to the default TLS listener. Domains configured in `router.domains` enforce their own mTLS requirement independently — client certificates are always required for those domains regardless of this setting. default: request router.disable_http: description: Disables the http listener on port specified by router.port. This cannot be set to true if enable_ssl is false. @@ -200,6 +202,33 @@ properties: router.only_trust_client_ca_certs: description: "When router.only_trust_client_ca_certs is true, router.client_ca_certs are the only trusted CA certs for client requests. When router.only_trust_client_ca_certs is false, router.client_ca_certs are trusted in addition to router.ca_certs and the CA certificates installed on the filesystem. This will have no affect if the `router.client_cert_validation` property is set to none." default: false + router.domains: + description: | + Array of domains requiring mutual TLS authentication. Each domain can have its own CA certificate pool, forwarded_client_cert mode, and xfcc_format. + For non-wildcard domains, the domain must match the request host exactly. + For wildcard domains (e.g., *.apps.identity), the wildcard must be the leftmost label and matches any single label. + + These domains enforce client certificate validation independently of `router.client_cert_validation` — clients connecting to these domains are always required to present a valid certificate signed by the domain's configured CA. + + xfcc_format controls the format of the X-Forwarded-Client-Cert header: + - "raw" (default): Full base64-encoded certificate (~1.5KB) + - "envoy": Compact Hash=;Subject="" format (~300 bytes) + default: [] + example: + - name: "*.apps.identity" + ca_certs: | + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + forwarded_client_cert: sanitize_set + xfcc_format: envoy + - name: "secure.example.com" + ca_certs: | + -----BEGIN CERTIFICATE----- + + -----END CERTIFICATE----- + forwarded_client_cert: forward + xfcc_format: raw router.backends.max_attempts: description: | Maximum number of attempts on failing requests against backend routes. diff --git a/jobs/gorouter/templates/gorouter.yml.erb b/jobs/gorouter/templates/gorouter.yml.erb index 47d9c30b0..b6ac37433 100644 --- a/jobs/gorouter/templates/gorouter.yml.erb +++ b/jobs/gorouter/templates/gorouter.yml.erb @@ -505,6 +505,57 @@ if p('router.client_ca_certs') params['client_ca_certs'] = client_ca_certs end +if_p('router.domains') do |domains| + if !domains.is_a?(Array) + raise 'router.domains must be provided as an array' + end + + processed_domains = [] + domains.each do |domain_config| + if !domain_config.is_a?(Hash) + raise 'Each entry in router.domains must be a hash' + end + + if !domain_config.key?('name') || domain_config['name'].nil? || domain_config['name'].strip.empty? + raise 'Each entry in router.domains must have a "name" key' + end + + if !domain_config.key?('ca_certs') || domain_config['ca_certs'].nil? || domain_config['ca_certs'].strip.empty? + raise 'Each entry in router.domains must have a "ca_certs" key with certificate content' + end + + processed_entry = { + 'domain' => domain_config['name'], + 'ca_certs' => domain_config['ca_certs'] + } + + if domain_config.key?('forwarded_client_cert') && !domain_config['forwarded_client_cert'].nil? + valid_modes = ['always_forward', 'forward', 'sanitize_set'] + mode = domain_config['forwarded_client_cert'] + unless valid_modes.include?(mode) + raise "Invalid forwarded_client_cert mode '#{mode}' for domain '#{domain_config['name']}'. Must be one of: #{valid_modes.join(', ')}" + end + processed_entry['forwarded_client_cert'] = mode + end + + if domain_config.key?('xfcc_format') && !domain_config['xfcc_format'].nil? + valid_formats = ['raw', 'envoy'] + format = domain_config['xfcc_format'] + unless valid_formats.include?(format) + raise "Invalid xfcc_format '#{format}' for domain '#{domain_config['name']}'. Must be one of: #{valid_formats.join(', ')}" + end + if processed_entry['forwarded_client_cert'] == 'always_forward' + raise "xfcc_format has no effect for domain '#{domain_config['name']}' when forwarded_client_cert is 'always_forward'. Remove xfcc_format or change forwarded_client_cert to 'sanitize_set'." + end + processed_entry['xfcc_format'] = format + end + + processed_domains << processed_entry + end + + params['domains'] = processed_domains +end + if_p('router.http_rewrite') do |r| params['http_rewrite'] = r end diff --git a/packages/routing-api/spec b/packages/routing-api/spec index f8a3f2ce4..47ba938f6 100644 --- a/packages/routing-api/spec +++ b/packages/routing-api/spec @@ -22,10 +22,10 @@ files: - code.cloudfoundry.org/vendor/code.cloudfoundry.org/lager/v3/internal/truncate/*.go # gosub - code.cloudfoundry.org/vendor/code.cloudfoundry.org/lager/v3/lagerflags/*.go # gosub - code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/*.go # gosub + - code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/lock/*.go # gosub - code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/cmd/locket/certauthority/*.go # gosub - code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/cmd/locket/config/*.go # gosub - code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/cmd/locket/testrunner/*.go # gosub - - code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/lock/*.go # gosub - code.cloudfoundry.org/vendor/code.cloudfoundry.org/locket/models/*.go # gosub - code.cloudfoundry.org/routing-api/*.go # gosub - code.cloudfoundry.org/routing-api/admin/*.go # gosub diff --git a/spec/gorouter_templates_spec.rb b/spec/gorouter_templates_spec.rb index 8be8f19bc..5d8707898 100644 --- a/spec/gorouter_templates_spec.rb +++ b/spec/gorouter_templates_spec.rb @@ -228,7 +228,7 @@ 'cert_chain' => ROUTE_SERVICES_CLIENT_TEST_CERT, 'private_key' => ROUTE_SERVICES_CLIENT_TEST_KEY, 'strict_signature_validation' => false, - 'enable_websockets' => true, + 'enable_websockets' => true }, 'frontend_idle_timeout' => 5, 'ip_local_port_range' => '1024 65535', @@ -629,9 +629,9 @@ it 'should configure the property' do expect(parsed_yaml['tls_pem'].length).to eq(2) expect(parsed_yaml['tls_pem'][0]).to eq('cert_chain' => TEST_CERT, - 'private_key' => 'test-key') + 'private_key' => 'test-key') expect(parsed_yaml['tls_pem'][1]).to eq('cert_chain' => TEST_CERT2, - 'private_key' => 'test-key2') + 'private_key' => 'test-key2') end end @@ -654,7 +654,7 @@ it 'should configure the property' do expect(parsed_yaml['tls_pem'].length).to eq(2) expect(parsed_yaml['tls_pem'][0]).to eq('cert_chain' => ECDSA_TEST_CERT, - 'private_key' => ECDSA_TEST_KEY) + 'private_key' => ECDSA_TEST_KEY) end end @@ -913,11 +913,11 @@ context 'when egress_blocklist is not set' do it 'parses to the default blocklist' do expect(parsed_yaml['route_services']['egress_blocklist']).to eq([ - '10.0.0.0/8', - '169.254.0.0/16', - '172.16.0.0/12', - '192.168.0.0/16' - ]) + '10.0.0.0/8', + '169.254.0.0/16', + '172.16.0.0/12', + '192.168.0.0/16' + ]) end end context 'when egress_blocklist is set' do @@ -1461,10 +1461,9 @@ end context 'logging' do - context 'when enable_detailed_attempts_logging is not provided' do it 'it does not set the correspoding extra access log values' do - expect(parsed_yaml['logging']['extra_access_log_fields']).not_to include(['backend_time', 'dial_time', 'dns_time', 'failed_attempts', 'failed_attempts_time', 'tls_time']) + expect(parsed_yaml['logging']['extra_access_log_fields']).not_to include(%w[backend_time dial_time dns_time failed_attempts failed_attempts_time tls_time]) end end @@ -1473,7 +1472,7 @@ deployment_manifest_fragment['router']['enable_log_attempts_details'] = true end it 'it properly sets the value' do - expect(parsed_yaml['logging']['extra_access_log_fields']).to eq(['failed_attempts', 'failed_attempts_time', 'dns_time', 'dial_time', 'tls_time', 'backend_time']) + expect(parsed_yaml['logging']['extra_access_log_fields']).to eq(%w[failed_attempts failed_attempts_time dns_time dial_time tls_time backend_time]) end end @@ -1500,7 +1499,7 @@ context 'to ["local_address", "foobar"]' do before do - deployment_manifest_fragment['router']['logging'] = { 'extra_access_log_fields' => ['local_address', 'foobar'] } + deployment_manifest_fragment['router']['logging'] = { 'extra_access_log_fields' => %w[local_address foobar] } end it 'still raises an error' do @@ -1516,7 +1515,7 @@ end it 'puts the extra_access_log_fields to the end to preserve order' do - expect(parsed_yaml['logging']['extra_access_log_fields']).to eq(['failed_attempts', 'failed_attempts_time', 'dns_time', 'dial_time', 'tls_time', 'backend_time', 'local_address']) + expect(parsed_yaml['logging']['extra_access_log_fields']).to eq(%w[failed_attempts failed_attempts_time dns_time dial_time tls_time backend_time local_address]) end end @@ -1747,6 +1746,204 @@ end end end + + describe 'router.domains' do + context 'when domains is not an array' do + before do + deployment_manifest_fragment['router']['domains'] = 'not-an-array' + end + + it 'raises an error' do + expect { parsed_yaml }.to raise_error(/router\.domains must be provided as an array/) + end + end + + context 'when a domain entry is not a hash' do + before do + deployment_manifest_fragment['router']['domains'] = ['not-a-hash'] + end + + it 'raises an error' do + expect { parsed_yaml }.to raise_error(/Each entry in router\.domains must be a hash/) + end + end + + context 'when a domain entry is missing the name key' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { 'ca_certs' => TEST_CERT } + ] + end + + it 'raises an error' do + expect { parsed_yaml }.to raise_error(/Each entry in router\.domains must have a "name" key/) + end + end + + context 'when a domain entry has an empty name' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { 'name' => ' ', 'ca_certs' => TEST_CERT } + ] + end + + it 'raises an error' do + expect { parsed_yaml }.to raise_error(/Each entry in router\.domains must have a "name" key/) + end + end + + context 'when a domain entry is missing the ca_certs key' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { 'name' => '*.apps.mtls.internal' } + ] + end + + it 'raises an error' do + expect { parsed_yaml }.to raise_error(/Each entry in router\.domains must have a "ca_certs" key/) + end + end + + context 'when a domain entry has empty ca_certs' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { 'name' => '*.apps.mtls.internal', 'ca_certs' => ' ' } + ] + end + + it 'raises an error' do + expect { parsed_yaml }.to raise_error(/Each entry in router\.domains must have a "ca_certs" key/) + end + end + + context 'when forwarded_client_cert has an invalid mode' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { + 'name' => '*.apps.mtls.internal', + 'ca_certs' => TEST_CERT, + 'forwarded_client_cert' => 'invalid_mode' + } + ] + end + + it 'raises an error' do + expect { parsed_yaml }.to raise_error(/Invalid forwarded_client_cert mode 'invalid_mode'/) + end + end + + context 'when xfcc_format has an invalid value' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { + 'name' => '*.apps.mtls.internal', + 'ca_certs' => TEST_CERT, + 'xfcc_format' => 'invalid_format' + } + ] + end + + it 'raises an error' do + expect { parsed_yaml }.to raise_error(/Invalid xfcc_format 'invalid_format'/) + end + end + + context 'when a valid domain is fully configured' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { + 'name' => '*.apps.mtls.internal', + 'ca_certs' => TEST_CERT, + 'forwarded_client_cert' => 'sanitize_set', + 'xfcc_format' => 'envoy' + } + ] + end + + it 'renders successfully' do + expect { parsed_yaml }.not_to raise_error + end + + it 'outputs the domain configuration' do + domains = parsed_yaml['domains'] + expect(domains.length).to eq(1) + expect(domains.first['domain']).to eq('*.apps.mtls.internal') + expect(domains.first['forwarded_client_cert']).to eq('sanitize_set') + expect(domains.first['xfcc_format']).to eq('envoy') + end + end + + context 'when always_forward is combined with xfcc_format' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { + 'name' => '*.apps.mtls.internal', + 'ca_certs' => TEST_CERT, + 'forwarded_client_cert' => 'always_forward', + 'xfcc_format' => 'envoy' + } + ] + end + + it 'raises an error because xfcc_format has no effect with always_forward' do + expect { parsed_yaml }.to raise_error(/xfcc_format has no effect.*always_forward/) + end + end + + context 'when always_forward is set without xfcc_format' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { + 'name' => '*.apps.mtls.internal', + 'ca_certs' => TEST_CERT, + 'forwarded_client_cert' => 'always_forward' + } + ] + end + + it 'renders successfully' do + expect { parsed_yaml }.not_to raise_error + end + end + + context 'when sanitize_set is combined with xfcc_format envoy' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { + 'name' => '*.apps.mtls.internal', + 'ca_certs' => TEST_CERT, + 'forwarded_client_cert' => 'sanitize_set', + 'xfcc_format' => 'envoy' + } + ] + end + + it 'renders successfully' do + expect { parsed_yaml }.not_to raise_error + end + + it 'sets xfcc_format in the output' do + domains = parsed_yaml['domains'] + expect(domains.first['xfcc_format']).to eq('envoy') + end + end + + context 'when xfcc_format is set without forwarded_client_cert' do + before do + deployment_manifest_fragment['router']['domains'] = [ + { + 'name' => '*.apps.mtls.internal', + 'ca_certs' => TEST_CERT, + 'xfcc_format' => 'envoy' + } + ] + end + + it 'renders successfully' do + expect { parsed_yaml }.not_to raise_error + end + end + end end describe 'healthchecker.yml' do @@ -1815,7 +2012,7 @@ before do deployment_manifest_fragment['router'] = { 'prometheus' => { - 'port' => 9090, + 'port' => 9090 } } end @@ -1840,7 +2037,7 @@ 'server_name' => 'example.org', 'cert' => TEST_CERT, 'key' => TEST_KEY, - 'ca_cert' => TEST_CERT2, + 'ca_cert' => TEST_CERT2 } } end @@ -1858,7 +2055,7 @@ before do deployment_manifest_fragment['router'] = { 'prometheus' => { - 'port' => 9090, + 'port' => 9090 } } end diff --git a/src/code.cloudfoundry.org/go.mod b/src/code.cloudfoundry.org/go.mod index 38ed954fb..f4c238635 100644 --- a/src/code.cloudfoundry.org/go.mod +++ b/src/code.cloudfoundry.org/go.mod @@ -1,23 +1,23 @@ module code.cloudfoundry.org -go 1.25.1 +go 1.25.0 replace github.com/cactus/go-statsd-client => github.com/cactus/go-statsd-client v2.0.2-0.20150911070441-6fa055a7b594+incompatible require ( - code.cloudfoundry.org/cfhttp/v2 v2.78.0 - code.cloudfoundry.org/clock v1.71.0 - code.cloudfoundry.org/debugserver v0.97.0 - code.cloudfoundry.org/diego-logging-client v0.106.0 - code.cloudfoundry.org/eventhub v0.73.0 + code.cloudfoundry.org/cfhttp/v2 v2.76.0 + code.cloudfoundry.org/clock v1.69.0 + code.cloudfoundry.org/debugserver v0.95.0 + code.cloudfoundry.org/diego-logging-client v0.104.0 + code.cloudfoundry.org/eventhub v0.71.0 code.cloudfoundry.org/go-loggregator/v9 v9.2.1 - code.cloudfoundry.org/go-metric-registry v0.0.0-20260522085328-be95096762f3 - code.cloudfoundry.org/lager/v3 v3.70.0 - code.cloudfoundry.org/localip v0.72.0 + code.cloudfoundry.org/go-metric-registry v0.0.0-20260505071949-70469c50517d + code.cloudfoundry.org/lager/v3 v3.68.0 + code.cloudfoundry.org/localip v0.70.0 code.cloudfoundry.org/locket v0.0.0-20260507165111-20f6e690be22 - code.cloudfoundry.org/tlsconfig v0.55.0 + code.cloudfoundry.org/tlsconfig v0.53.0 github.com/armon/go-proxyproto v0.1.0 - github.com/cactus/go-statsd-client v3.2.1+incompatible + github.com/cactus/go-statsd-client v0.0.0-00010101000000-000000000000 github.com/cloudfoundry-community/go-uaa v0.3.6 github.com/cloudfoundry/cf-test-helpers/v2 v2.13.0 github.com/cloudfoundry/custom-cats-reporters v0.0.2 @@ -25,12 +25,12 @@ require ( github.com/cloudfoundry/sonde-go v0.0.0-20251217143644-d1670a435f2a github.com/go-sql-driver/mysql v1.10.0 github.com/golang-jwt/jwt/v4 v4.5.2 - github.com/kisielk/errcheck v1.20.0 - github.com/nats-io/nats-server/v2 v2.14.1 - github.com/nats-io/nats.go v1.52.0 + github.com/kisielk/errcheck v1.10.0 + github.com/nats-io/nats-server/v2 v2.14.0 + github.com/nats-io/nats.go v1.51.0 github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d - github.com/onsi/ginkgo/v2 v2.29.0 - github.com/onsi/gomega v1.41.0 + github.com/onsi/ginkgo/v2 v2.28.3 + github.com/onsi/gomega v1.40.0 github.com/openzipkin/zipkin-go v0.4.3 github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 github.com/tedsuo/ifrit v0.0.0-20260418191334-846868129986 @@ -38,14 +38,14 @@ require ( github.com/urfave/cli v1.22.17 github.com/urfave/negroni/v3 v3.1.1 github.com/vito/go-sse v1.1.3 - go.step.sm/crypto v0.81.0 + go.step.sm/crypto v0.77.9 go.uber.org/zap v1.28.0 go.uber.org/zap/exp v0.3.0 - golang.org/x/crypto v0.52.0 - golang.org/x/net v0.55.0 + golang.org/x/crypto v0.51.0 + golang.org/x/net v0.54.0 golang.org/x/oauth2 v0.36.0 golang.org/x/tools v0.45.0 - google.golang.org/grpc v1.81.1 + google.golang.org/grpc v1.81.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 gorm.io/driver/mysql v1.6.0 @@ -55,8 +55,8 @@ require ( require ( code.cloudfoundry.org/bbs v0.0.0-20260507155651-045cbe358842 // indirect - code.cloudfoundry.org/durationjson v0.73.0 // indirect - code.cloudfoundry.org/go-diodes v0.0.0-20260518082450-53acbbed6d0f // indirect + code.cloudfoundry.org/durationjson v0.71.0 // indirect + code.cloudfoundry.org/go-diodes v0.0.0-20260504113438-abdf05667e78 // indirect code.cloudfoundry.org/inigo v0.0.0-20210615140442-4bdc4f6e44d5 // indirect filippo.io/edwards25519 v1.2.0 // indirect github.com/Masterminds/semver/v3 v3.5.0 // indirect @@ -74,11 +74,11 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-tpm v0.9.8 // indirect - github.com/google/pprof v0.0.0-20260507013755-92041b743c96 // indirect + github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 // indirect github.com/honeycombio/libhoney-go v1.27.1 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgx/v5 v5.9.2 // indirect + github.com/jackc/pgx/v5 v5.9.1 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect @@ -102,9 +102,9 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/mod v0.36.0 // indirect golang.org/x/sync v0.20.0 // indirect - golang.org/x/sys v0.45.0 // indirect + golang.org/x/sys v0.44.0 // indirect golang.org/x/text v0.37.0 // indirect golang.org/x/time v0.15.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260523011958-0a33c5d7ca68 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 // indirect gopkg.in/alexcesaro/statsd.v2 v2.0.0 // indirect ) diff --git a/src/code.cloudfoundry.org/go.sum b/src/code.cloudfoundry.org/go.sum index cc9c633da..f6f3b7d87 100644 --- a/src/code.cloudfoundry.org/go.sum +++ b/src/code.cloudfoundry.org/go.sum @@ -594,34 +594,34 @@ cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= code.cloudfoundry.org/bbs v0.0.0-20260507155651-045cbe358842 h1:gxO1l3XeHR+KKEsOb7MeZbcuOz7HoQy5/3Lghb828l4= code.cloudfoundry.org/bbs v0.0.0-20260507155651-045cbe358842/go.mod h1:XKlGVVXFi5EcHHMPzw3xgONK9PeEZuUbIC43XNwxD10= -code.cloudfoundry.org/cfhttp/v2 v2.78.0 h1:eN13Xt0rGl91+gYx2HHU8epL+ngKcZLuIrRin7+m19o= -code.cloudfoundry.org/cfhttp/v2 v2.78.0/go.mod h1:Oj2SjepVpqXZ1/+EdqmKRTjwvUid2HcgR8fF8+LmxsU= -code.cloudfoundry.org/clock v1.71.0 h1:hKKqBISk8mMAOT5W2n31qkRWhrNHwWqVhudQzvHEh3A= -code.cloudfoundry.org/clock v1.71.0/go.mod h1:4PHgcKBHLUmzfok5UjDvKlDdFxjd+miuMiF9F325Y94= -code.cloudfoundry.org/debugserver v0.97.0 h1:LAmMK0TcUkbN3+ibPuT2BdhiC1FU6svnITH7Mg77znw= -code.cloudfoundry.org/debugserver v0.97.0/go.mod h1:fMwAfto0a6ZWwYC0VOpiw4LG7g4lzo1h/kTt0iywhQ8= -code.cloudfoundry.org/diego-logging-client v0.106.0 h1:Ono2/BO8kna6abDWkQyfpAzUPCC3BR/syWQYzKczh/4= -code.cloudfoundry.org/diego-logging-client v0.106.0/go.mod h1:E2LnBrNB0jwpY0+gSXgXN0bgnqFn84spPAqUdWIVYMI= -code.cloudfoundry.org/durationjson v0.73.0 h1:f0gez36QrL7/459s/TpXDNVR8V4M4ouLSH9g7noARdA= -code.cloudfoundry.org/durationjson v0.73.0/go.mod h1:93X2uciANvU4gfxq2Ui93yNiWwL3wYlSndqVxi5ek00= -code.cloudfoundry.org/eventhub v0.73.0 h1:Es69j0SFs08fiHWMqAxe6vHUqPXQKsKC/nfpaCSXCHY= -code.cloudfoundry.org/eventhub v0.73.0/go.mod h1:prUim4SrlsC7T7ReVlicUsUbJJDzTzjgmvAwOreUcig= -code.cloudfoundry.org/go-diodes v0.0.0-20260518082450-53acbbed6d0f h1:64yICzxRPmSlKiwWc8EK7Ion6zQzbfLE8VVnOvAyRHM= -code.cloudfoundry.org/go-diodes v0.0.0-20260518082450-53acbbed6d0f/go.mod h1:CBNKjs+CBCb9Q83t8vxzqctA/wa5bonUXh1WQDFxZaY= +code.cloudfoundry.org/cfhttp/v2 v2.76.0 h1:sRfGrEvUD0O08UaO6G+tRlFS2vkkEn3bfvUtZuWTcPE= +code.cloudfoundry.org/cfhttp/v2 v2.76.0/go.mod h1:WMhvXg+LpJA+gzHgDJBT1vWZ45Pjqrptcq0WuexKb2k= +code.cloudfoundry.org/clock v1.69.0 h1:1hR864FRXyCcjw+1p77iUoxTIDgoXVvhblIsOrXaxOM= +code.cloudfoundry.org/clock v1.69.0/go.mod h1:+ikbfwCwwAad/NxA3wKkF9BmP4UYID6/gWDZnMtWXjU= +code.cloudfoundry.org/debugserver v0.95.0 h1:em5my9WbVackEw0DEXzYNkavpEWnALdQ1qNaPL5Ecq8= +code.cloudfoundry.org/debugserver v0.95.0/go.mod h1:rF2LuR475W2osX7rjp8EU3Va9tDnbuIyu0dl49rzRWo= +code.cloudfoundry.org/diego-logging-client v0.104.0 h1:KsUA+RCcyk2rOidM55vPrrZ1fI9/fWYy05jR3+myDEE= +code.cloudfoundry.org/diego-logging-client v0.104.0/go.mod h1:WhiAuuGDTX8IPsPBkRQvlIxn6FcOhFkP+kWoJXa4YqA= +code.cloudfoundry.org/durationjson v0.71.0 h1:gYphqVJ26+eowBnqLvNf4vhe5vohumOs8uIzKAaEPW8= +code.cloudfoundry.org/durationjson v0.71.0/go.mod h1:JCMQKSBPyH4a6md9TiC+ag2ILAY9UAxRwo+ltmlio2Q= +code.cloudfoundry.org/eventhub v0.71.0 h1:hmpn7g4dfDerhYeqMnpnSgpms7G0uK3rQ4B3zrTgb1k= +code.cloudfoundry.org/eventhub v0.71.0/go.mod h1:OX58wkIUJPDnDs/3UWwxOvirGv5V0Sa5YZVWYgX9a5s= +code.cloudfoundry.org/go-diodes v0.0.0-20260504113438-abdf05667e78 h1:5bGjlbR/P1omITVWptbn11zZAVOZg2JiYkQzfol/7qM= +code.cloudfoundry.org/go-diodes v0.0.0-20260504113438-abdf05667e78/go.mod h1:h9KGzD7HrNJeTn9wD8V+C4dy9a6KMj5MT3AEqD1wp3Y= code.cloudfoundry.org/go-loggregator/v9 v9.2.1 h1:S6Lgg5UJbhh2bt2TGQxs6R00CF8PrUA3GFPYDxy56Fk= code.cloudfoundry.org/go-loggregator/v9 v9.2.1/go.mod h1:FTFFruqGeOhVCDFvyLgl8EV8YW63NNwRzLhxJcporu8= -code.cloudfoundry.org/go-metric-registry v0.0.0-20260522085328-be95096762f3 h1:y8mfLMQstjHfJp3NxYCgO9DkKPpSdMSdsewoSLqypAI= -code.cloudfoundry.org/go-metric-registry v0.0.0-20260522085328-be95096762f3/go.mod h1:4Y0F7YJbUSKzALmhX0DSsY5YgO+mF/4ik7oYbSiiaeI= +code.cloudfoundry.org/go-metric-registry v0.0.0-20260505071949-70469c50517d h1:PGvZwU1y2Wb6TVJkJMXTUkBNytBIBK0WYju3tAc7k60= +code.cloudfoundry.org/go-metric-registry v0.0.0-20260505071949-70469c50517d/go.mod h1:4BVWLtSS1wpulR7XGbeQQ6CSPyujbmMkEzNSEsj3yq8= code.cloudfoundry.org/inigo v0.0.0-20210615140442-4bdc4f6e44d5 h1:XVhLtnvbIlLQh7L0KADVFjd2dfgXVcOpqPLpMtg/IZA= code.cloudfoundry.org/inigo v0.0.0-20210615140442-4bdc4f6e44d5/go.mod h1:1ZB1JCh2FAp+SqX79ve6dc8YREvbsziULEOncAilX4Q= -code.cloudfoundry.org/lager/v3 v3.70.0 h1:Zj494qLIhDaHYXY/o9kso9gZmUDN2QivZcQWc6nmGiA= -code.cloudfoundry.org/lager/v3 v3.70.0/go.mod h1:jeHA5iHYjc51JC7z8R464l6UQs7Cws9kb9QfyKxtP0U= -code.cloudfoundry.org/localip v0.72.0 h1:kLSH+5w07CjxEY2f/AMusJT7es7bmfdo2VxF9ODYXVc= -code.cloudfoundry.org/localip v0.72.0/go.mod h1:f8m+EbkPIlrB2k4iUjkovzO8t8iUnac5tmJHcTGV8nA= +code.cloudfoundry.org/lager/v3 v3.68.0 h1:b33D5fOtsIxbkZ38sDBF+caplshMLE9FgyTOkZWK0LY= +code.cloudfoundry.org/lager/v3 v3.68.0/go.mod h1:BZ2gnIin10+CWClXj0ixcE9BHlaydZehY643zvKAO5c= +code.cloudfoundry.org/localip v0.70.0 h1:IxPUhEuLciY9Q1UyJbnWAKaPz7tI6jrCRqjB23Liq58= +code.cloudfoundry.org/localip v0.70.0/go.mod h1:nLRBAdF4oO4F+fK8aebJCnRMBgQOILvbtF3HbLiCJW8= code.cloudfoundry.org/locket v0.0.0-20260507165111-20f6e690be22 h1:4XbpyOIuXKcYFPmrAvBnp0zWaCn1NI1X7N/0nit6q+g= code.cloudfoundry.org/locket v0.0.0-20260507165111-20f6e690be22/go.mod h1:AwHLRkdXtttLXNB8RHgLfErJ2kKafH62AR2OClhy6xI= -code.cloudfoundry.org/tlsconfig v0.55.0 h1:DuMYemm5TIhnez4x6MlUwn2izeJz8IV5V989iLyuYrw= -code.cloudfoundry.org/tlsconfig v0.55.0/go.mod h1:ve3jSEWJpofoU/tls0ov1uj/sx8J+TW0cpSpOGFUeVo= +code.cloudfoundry.org/tlsconfig v0.53.0 h1:ajprkio3g4V+C0AUJt3rXkkA0il+3sQZ9dJMRQ/e7Ug= +code.cloudfoundry.org/tlsconfig v0.53.0/go.mod h1:DMYiC50mOZC38kVQChNoHvLveqD+xohYJgfO9yusAFk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= filippo.io/edwards25519 v1.2.0/go.mod h1:xzAOLCNug/yB62zG1bQ8uziwrIqIuxhctzJT18Q77mc= @@ -857,8 +857,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20260507013755-92041b743c96 h1:YDDnaZ9afWajDboPMt9Vikqca/yWAX7KAxVzb4lJU1M= -github.com/google/pprof v0.0.0-20260507013755-92041b743c96/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= +github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 h1:EwtI+Al+DeppwYX2oXJCETMO23COyaKGP6fHVpkpWpg= +github.com/google/pprof v0.0.0-20260402051712-545e8a4df936/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -897,8 +897,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw= -github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= +github.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc= +github.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= @@ -913,8 +913,8 @@ github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+ github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/errcheck v1.20.0 h1:9rwHBNKzd4wkDWcROy3DvFGNqEPlkxBg305rvk7HabI= -github.com/kisielk/errcheck v1.20.0/go.mod h1:O+f80MKNwX8Oor2jwgpeQ9An7uJm+hRSgT+h22knRJU= +github.com/kisielk/errcheck v1.10.0 h1:Lvs/YAHP24YKg08LA8oDw2z9fJVme090RAXd90S+rrw= +github.com/kisielk/errcheck v1.10.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= @@ -951,10 +951,10 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/nats-io/jwt/v2 v2.8.1 h1:V0xpGuD/N8Mi+fQNDynXohVvp7ZztevW5io8CUWlPmU= github.com/nats-io/jwt/v2 v2.8.1/go.mod h1:nWnOEEiVMiKHQpnAy4eXlizVEtSfzacZ1Q43LIRavZg= -github.com/nats-io/nats-server/v2 v2.14.1 h1:wXs/a5fw9Hzm3CvuzLxGeIwpjPulSa7gMT3eSuhGkcg= -github.com/nats-io/nats-server/v2 v2.14.1/go.mod h1:4N17zLpuS7WMbG8T9gsE2B7z9hC9PraPyulVBfpK6nU= -github.com/nats-io/nats.go v1.52.0 h1:n3avV4VBsCgsdwh71TppsTwtv+QdPs7ntSKM8qJLGsc= -github.com/nats-io/nats.go v1.52.0/go.mod h1:26HypzazeOkyO3/mqd1zZd53STJN0EjCYF9Uy2ZOBno= +github.com/nats-io/nats-server/v2 v2.14.0 h1:+8q0HrDFotwLLcGH/legOEOnowunhK+aZ4GYBIWpQlM= +github.com/nats-io/nats-server/v2 v2.14.0/go.mod h1:ImVUUDvfClJbb6cuJQRc1VmgDCXKM5ds0OoiG9MVOKo= +github.com/nats-io/nats.go v1.51.0 h1:ByW84XTz6W03GSSsygsZcA+xgKK8vPGaa/FCAAEHnAI= +github.com/nats-io/nats.go v1.51.0/go.mod h1:26HypzazeOkyO3/mqd1zZd53STJN0EjCYF9Uy2ZOBno= github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4= github.com/nats-io/nkeys v0.4.15/go.mod h1:CpMchTXC9fxA5zrMo4KpySxNjiDVvr8ANOSZdiNfUrs= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -981,8 +981,8 @@ github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxm github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo= github.com/onsi/ginkgo/v2 v2.9.2/go.mod h1:WHcJJG2dIlcCqVfBAwUCrJxSPFb6v4azBwgxeMeDuts= github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM= -github.com/onsi/ginkgo/v2 v2.29.0 h1:rfh+ZFjgJhYWRoIqVf3Uwx/W20yLrcrE2h2GmYVRaag= -github.com/onsi/ginkgo/v2 v2.29.0/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= +github.com/onsi/ginkgo/v2 v2.28.3 h1:4JvMdwtFU0imd8fHx25OJXoDMRexnf8v5NHKYSTTji4= +github.com/onsi/ginkgo/v2 v2.28.3/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= @@ -997,8 +997,8 @@ github.com/onsi/gomega v1.27.1/go.mod h1:aHX5xOykVYzWOV4WqQy0sy8BQptgukenXpCXfad github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw= github.com/onsi/gomega v1.27.4/go.mod h1:riYq/GJKh8hhoM01HN6Vmuy93AarCXCBGpvFDK3q3fQ= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= -github.com/onsi/gomega v1.41.0 h1:OwKp4pXNgVxf6sCplzYo794OFNuoL2q2SBMU5NSWOjA= -github.com/onsi/gomega v1.41.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A= +github.com/onsi/gomega v1.40.0 h1:Vtol0e1MghCD2ZVIilPDIg44XSL9l2QAn8ZNaljWcJc= +github.com/onsi/gomega v1.40.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A= github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= @@ -1116,8 +1116,8 @@ go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLh go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= -go.step.sm/crypto v0.81.0 h1:e+ouzpNt3Xm4dp7HGXhgYB5y4iFik3vh3phHKWmvugU= -go.step.sm/crypto v0.81.0/go.mod h1:fsTizqQeASjTXnbv9O00XtRlIuXRkCdoRiJNyXGQujc= +go.step.sm/crypto v0.77.9 h1:gC/z6/XBlLpq9suHQxbcDS32QSGggpisIZVJr65LDJk= +go.step.sm/crypto v0.77.9/go.mod h1:/5BzDlwYA7C1q6h9OIv0+oR8lbQvK+rTGeBmLLl7hIo= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -1140,8 +1140,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= -golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1267,8 +1267,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1405,8 +1405,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= -golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= 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= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1729,8 +1729,8 @@ google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOl google.golang.org/genproto v0.0.0-20230330154414-c0448cd141ea/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230331144136-dcfb400f0633/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260523011958-0a33c5d7ca68 h1:PvEgGJf9C/1u5CHkInMg7UFYYUoiaQmW2LbtH0pjB78= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260523011958-0a33c5d7ca68/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 h1:pfIbyB44sWzHiCpRqIen67ZQnVXSfIxWrqUMk1qwODE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1773,8 +1773,8 @@ google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5v google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ= -google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= +google.golang.org/grpc v1.81.0 h1:W3G9N3KQf3BU+YuCtGKJk0CmxQNbAISICD/9AORxLIw= +google.golang.org/grpc v1.81.0/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/examples v0.0.0-20230512210959-5dcfb37c0b43/go.mod h1:irORyHPQXotoshbRTZVFvPDcfTfFHL23efQeop+H45M= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/src/code.cloudfoundry.org/gorouter/accesslog/schema/access_log_record.go b/src/code.cloudfoundry.org/gorouter/accesslog/schema/access_log_record.go index 126381b39..f5988642f 100644 --- a/src/code.cloudfoundry.org/gorouter/accesslog/schema/access_log_record.go +++ b/src/code.cloudfoundry.org/gorouter/accesslog/schema/access_log_record.go @@ -127,6 +127,17 @@ type AccessLogRecord struct { GorouterTime float64 LocalAddress string + + // Identity-aware routing authorization fields. + // CallerCFApp/Space/Org are the CF identity fields from the client certificate. + CallerCFApp string + CallerCFSpace string + CallerCFOrg string + // RoutePolicy identifies the route policy rule that matched or caused denial. + // Empty ("-") when no route policies are configured or enforcement is disabled. + RoutePolicy string + // TlsSNI is the SNI used during TLS (logged on 421 rejections). + TlsSNI string } func (r *AccessLogRecord) formatStartedAt() string { @@ -316,6 +327,23 @@ func (r *AccessLogRecord) makeRecord(performTruncate bool) []byte { b.WriteString(`x_cf_routererror:`) b.WriteDashOrStringValue(r.RouterError) + b.AppendSpaces(false) + // #nosec G104 + b.WriteString(` tls_sni:`) + b.WriteDashOrStringValue(r.TlsSNI) + // #nosec G104 + b.WriteString(` caller_cf_app:`) + b.WriteDashOrStringValue(r.CallerCFApp) + // #nosec G104 + b.WriteString(` caller_cf_space:`) + b.WriteDashOrStringValue(r.CallerCFSpace) + // #nosec G104 + b.WriteString(` caller_cf_org:`) + b.WriteDashOrStringValue(r.CallerCFOrg) + // #nosec G104 + b.WriteString(` route_policy:`) + b.WriteDashOrStringValue(r.RoutePolicy) + r.addExtraHeaders(b, performTruncate) return b.Bytes() diff --git a/src/code.cloudfoundry.org/gorouter/accesslog/schema/access_log_record_test.go b/src/code.cloudfoundry.org/gorouter/accesslog/schema/access_log_record_test.go index 4fe49af9c..a0d220da8 100644 --- a/src/code.cloudfoundry.org/gorouter/accesslog/schema/access_log_record_test.go +++ b/src/code.cloudfoundry.org/gorouter/accesslog/schema/access_log_record_test.go @@ -270,7 +270,7 @@ var _ = Describe("AccessLogRecord", func() { Eventually(r).Should(Say(`"1.2.3.4:1234" x_forwarded_for:"FakeProxy1, FakeProxy2" `)) Eventually(r).Should(Say(`x_forwarded_proto:"FakeOriginalRequestProto" `)) Eventually(r).Should(Say(`vcap_request_id:"abc-123-xyz-pdq" response_time:60.000000 gorouter_time:10.000000 app_id:"FakeApplicationId" `)) - Eventually(r).Should(Say(`app_index:"3" instance_id:"FakeInstanceId" x_cf_routererror:"some-router-error" cache_control:"no-cache" accept_encoding:"gzip, deflate" `)) + Eventually(r).Should(Say(`app_index:"3" instance_id:"FakeInstanceId" x_cf_routererror:"some-router-error" tls_sni:"-" caller_cf_app:"-" caller_cf_space:"-" caller_cf_org:"-" route_policy:"-" cache_control:"no-cache" accept_encoding:"gzip, deflate" `)) Eventually(r).Should(Say(`if_match:"737060cd8c284d8af7ad3082f209582d" doesnt_exist:"-"`)) }) }) diff --git a/src/code.cloudfoundry.org/gorouter/config/config.go b/src/code.cloudfoundry.org/gorouter/config/config.go index 8be9f587e..b57f66dda 100644 --- a/src/code.cloudfoundry.org/gorouter/config/config.go +++ b/src/code.cloudfoundry.org/gorouter/config/config.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "log/slog" + "net" "net/url" "os" "runtime" @@ -36,6 +37,10 @@ const ( REDACT_QUERY_PARMS_NONE string = "none" REDACT_QUERY_PARMS_ALL string = "all" REDACT_QUERY_PARMS_HASH string = "hash" + + // XFCC format constants for mTLS domains + XFCC_FORMAT_RAW string = "raw" // Full base64-encoded certificate + XFCC_FORMAT_ENVOY string = "envoy" // Hash=;Subject="" format ) var ( @@ -45,6 +50,7 @@ var ( AllowedShardingModes = []string{SHARD_ALL, SHARD_SEGMENTS, SHARD_SHARED_AND_SEGMENTS} AllowedForwardedClientCertModes = []string{ALWAYS_FORWARD, FORWARD, SANITIZE_SET} AllowedQueryParmRedactionModes = []string{REDACT_QUERY_PARMS_NONE, REDACT_QUERY_PARMS_ALL, REDACT_QUERY_PARMS_HASH} + AllowedXFCCFormats = []string{XFCC_FORMAT_RAW, XFCC_FORMAT_ENVOY} ) type StringSet map[string]struct{} @@ -368,6 +374,17 @@ func InitClientCertMetadataRules(rules []VerifyClientCertificateMetadataRule, ce return nil } +// MtlsDomainConfig defines TLS settings for a specific domain that requires mutual TLS +type MtlsDomainConfig struct { + Domain string `yaml:"domain"` + CAPool *x509.CertPool `yaml:"-"` + CACerts string `yaml:"ca_certs"` + ForwardedClientCert string `yaml:"forwarded_client_cert"` + XFCCFormat string `yaml:"xfcc_format"` // "raw" (default) or "envoy" + // Computed fields + RequireClientCert bool `yaml:"-"` // Always true for mTLS domains +} + type Config struct { Status StatusConfig `yaml:"status,omitempty"` Nats NatsConfig `yaml:"nats,omitempty"` @@ -394,6 +411,13 @@ type Config struct { ClientCACerts string `yaml:"client_ca_certs,omitempty"` ClientCAPool *x509.CertPool `yaml:"-"` + // Domains configures domains that require client certificates (mTLS). + // Corresponds to router.domains in the BOSH manifest (RFC: router.domains). + // Routes on these domains will require valid instance identity certificates. + Domains []MtlsDomainConfig `yaml:"domains,omitempty"` + // Computed: map of domain -> config for fast lookup + mtlsDomainMap map[string]*MtlsDomainConfig `yaml:"-"` + SkipSSLValidation bool `yaml:"skip_ssl_validation,omitempty"` ForwardedClientCert string `yaml:"forwarded_client_cert,omitempty"` ForceForwardedProtoHttps bool `yaml:"force_forwarded_proto_https,omitempty"` @@ -802,6 +826,9 @@ func (c *Config) Process() error { if err := c.buildClientCertPool(); err != nil { return err } + if err := c.processMtlsDomains(); err != nil { + return err + } return nil } @@ -902,6 +929,62 @@ func (c *Config) buildClientCertPool() error { return nil } +func (c *Config) processMtlsDomains() error { + // Initialize mTLS domain map + c.mtlsDomainMap = make(map[string]*MtlsDomainConfig) + + for i := range c.Domains { + domain := &c.Domains[i] + domain.RequireClientCert = true + + // Validate forwarded_client_cert mode + if domain.ForwardedClientCert == "" { + domain.ForwardedClientCert = SANITIZE_SET // Default to most secure + } + if !slices.Contains(AllowedForwardedClientCertModes, domain.ForwardedClientCert) { + return fmt.Errorf("domains[%d].forwarded_client_cert must be one of %v", + i, AllowedForwardedClientCertModes) + } + + // Validate xfcc_format + if domain.XFCCFormat == "" { + domain.XFCCFormat = XFCC_FORMAT_RAW // Default to raw for backwards compatibility + } + if !slices.Contains(AllowedXFCCFormats, domain.XFCCFormat) { + return fmt.Errorf("domains[%d].xfcc_format must be one of %v", + i, AllowedXFCCFormats) + } + if domain.XFCCFormat != XFCC_FORMAT_RAW && domain.ForwardedClientCert == ALWAYS_FORWARD { + return fmt.Errorf("domains[%d].xfcc_format has no effect when forwarded_client_cert is 'always_forward'; remove xfcc_format or change forwarded_client_cert to 'sanitize_set'", + i) + } + + // Build CA pool for this domain + if domain.CACerts != "" { + pool := x509.NewCertPool() + if !pool.AppendCertsFromPEM([]byte(domain.CACerts)) { + return fmt.Errorf("domains[%d].ca_certs contains invalid certificates", i) + } + domain.CAPool = pool + } else { + return fmt.Errorf("domains[%d].ca_certs is required", i) + } + + // Validate domain is not empty + if domain.Domain == "" { + return fmt.Errorf("domains[%d].domain is required", i) + } + + // Normalize domain to lowercase for case-insensitive matching (RFC 1035) + // Both the map key AND the stored Domain field are lowercased so that + // downstream code (e.g., domainMatches) can do case-insensitive comparisons. + domain.Domain = strings.ToLower(domain.Domain) + c.mtlsDomainMap[domain.Domain] = domain + } + + return nil +} + func convertCipherStringToInt(cipherStrs []string, cipherMap map[string]uint16) ([]uint16, error) { ciphers := []uint16{} for _, cipher := range cipherStrs { @@ -937,6 +1020,45 @@ func (c *Config) RoutingApiEnabled() bool { return (c.RoutingApi.Uri != "") && (c.RoutingApi.Port != 0) } +// GetMtlsDomainConfig returns the mTLS domain configuration for a given host. +// It checks for exact matches first, then wildcard matches (e.g., *.apps.mtls.internal). +// Matching is case-insensitive per RFC 1035 (DNS hostnames). +// Returns nil if the host is not an mTLS domain. +func (c *Config) GetMtlsDomainConfig(host string) *MtlsDomainConfig { + // Strip port if present (e.g., "app.example.com:443" → "app.example.com") + // This ensures consistent matching regardless of whether clients include explicit ports + if h, _, err := net.SplitHostPort(host); err == nil { + host = h + } + + // Normalize to lowercase for case-insensitive matching (RFC 1035) + host = strings.ToLower(host) + + // Check exact match first + if cfg, ok := c.mtlsDomainMap[host]; ok { + return cfg + } + // Check wildcard match (e.g., *.apps.mtls.internal) + // Wildcard patterns only match a single DNS label, not multiple levels. + // e.g., "app.domain.com" matches "*.domain.com" but "deep.sub.domain.com" does not. + // Note: SplitN(host, ".", 2) guarantees parts[0] never contains a dot, so + // multi-level subdomain protection is inherent — only the first label is stripped. + parts := strings.SplitN(host, ".", 2) + if len(parts) == 2 { + suffix := parts[1] + wildcardDomain := "*." + suffix + if cfg, ok := c.mtlsDomainMap[wildcardDomain]; ok { + return cfg + } + } + return nil +} + +// IsMtlsDomain returns true if the given host is configured as an mTLS domain +func (c *Config) IsMtlsDomain(host string) bool { + return c.GetMtlsDomainConfig(host) != nil +} + func (c *Config) Initialize(configYAML []byte) error { return yaml.Unmarshal(configYAML, &c) } diff --git a/src/code.cloudfoundry.org/gorouter/config/config_test.go b/src/code.cloudfoundry.org/gorouter/config/config_test.go index d6b2ff33e..e9bf7d964 100644 --- a/src/code.cloudfoundry.org/gorouter/config/config_test.go +++ b/src/code.cloudfoundry.org/gorouter/config/config_test.go @@ -2043,6 +2043,244 @@ drain_timeout: 60s }) }) + + Describe("GetMtlsDomainConfig", func() { + var certChain test_util.CertChain + + BeforeEach(func() { + certChain = test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + cfgForSnippet.Domains = []MtlsDomainConfig{ + { + Domain: "*.apps.identity", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "exact.example.com", + XFCCFormat: "raw", + CACerts: string(certChain.CACertPEM), + }, + } + err := config.Initialize(createYMLSnippet(cfgForSnippet)) + Expect(err).ToNot(HaveOccurred()) + err = config.Process() + Expect(err).ToNot(HaveOccurred()) + }) + + Context("when host includes explicit port", func() { + It("strips port and matches wildcard domain", func() { + cfg := config.GetMtlsDomainConfig("xfcc-tester.apps.identity:443") + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Domain).To(Equal("*.apps.identity")) + Expect(cfg.XFCCFormat).To(Equal("envoy")) + }) + + It("strips port and matches exact domain", func() { + cfg := config.GetMtlsDomainConfig("exact.example.com:8443") + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Domain).To(Equal("exact.example.com")) + Expect(cfg.XFCCFormat).To(Equal("raw")) + }) + }) + + Context("when host does not include port", func() { + It("matches wildcard domain without port", func() { + cfg := config.GetMtlsDomainConfig("xfcc-tester.apps.identity") + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Domain).To(Equal("*.apps.identity")) + Expect(cfg.XFCCFormat).To(Equal("envoy")) + }) + + It("matches exact domain without port", func() { + cfg := config.GetMtlsDomainConfig("exact.example.com") + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Domain).To(Equal("exact.example.com")) + Expect(cfg.XFCCFormat).To(Equal("raw")) + }) + }) + + Context("when host is not an mTLS domain", func() { + It("returns nil for non-matching host with port", func() { + cfg := config.GetMtlsDomainConfig("other.example.com:443") + Expect(cfg).To(BeNil()) + }) + + It("returns nil for non-matching host without port", func() { + cfg := config.GetMtlsDomainConfig("other.example.com") + Expect(cfg).To(BeNil()) + }) + + It("returns nil for multi-level subdomain (wildcard should only match single label)", func() { + cfg := config.GetMtlsDomainConfig("deep.sub.apps.identity") + Expect(cfg).To(BeNil()) + }) + }) + + Context("case-insensitive matching per RFC 1035", func() { + It("matches wildcard domain with uppercase host", func() { + cfg := config.GetMtlsDomainConfig("XFCC-TESTER.APPS.IDENTITY") + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Domain).To(Equal("*.apps.identity")) + }) + + It("matches exact domain with mixed case host", func() { + cfg := config.GetMtlsDomainConfig("Exact.Example.Com") + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Domain).To(Equal("exact.example.com")) + }) + + It("matches with uppercase host and port", func() { + cfg := config.GetMtlsDomainConfig("EXACT.EXAMPLE.COM:443") + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Domain).To(Equal("exact.example.com")) + }) + }) + + Context("when domain is configured with mixed case (Thread 16: domain.Domain not lowercased)", func() { + BeforeEach(func() { + // Configure domains with MIXED CASE to expose the bug where + // domain.Domain retains original casing instead of being normalized + cfgForSnippet.Domains = []MtlsDomainConfig{ + { + Domain: "*.Apps.Identity", // Mixed case - should be normalized + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "Exact.EXAMPLE.Com", // Mixed case - should be normalized + XFCCFormat: "raw", + CACerts: string(certChain.CACertPEM), + }, + } + err := config.Initialize(createYMLSnippet(cfgForSnippet)) + Expect(err).ToNot(HaveOccurred()) + err = config.Process() + Expect(err).ToNot(HaveOccurred()) + }) + + It("normalizes cfg.Domain to lowercase for wildcard domain", func() { + cfg := config.GetMtlsDomainConfig("backend.apps.identity") + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Domain).To(Equal("*.apps.identity")) + }) + + It("normalizes cfg.Domain to lowercase for exact domain", func() { + cfg := config.GetMtlsDomainConfig("exact.example.com") + Expect(cfg).ToNot(BeNil()) + Expect(cfg.Domain).To(Equal("exact.example.com")) + }) + + It("matches lowercase host against mixed-case configured domain", func() { + cfg := config.GetMtlsDomainConfig("backend.apps.identity") + Expect(cfg).ToNot(BeNil()) + }) + + It("matches uppercase host against mixed-case configured domain", func() { + cfg := config.GetMtlsDomainConfig("BACKEND.APPS.IDENTITY") + Expect(cfg).ToNot(BeNil()) + }) + }) + }) + + Describe("IsMtlsDomain", func() { + var certChain test_util.CertChain + + BeforeEach(func() { + certChain = test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + cfgForSnippet.Domains = []MtlsDomainConfig{ + { + Domain: "*.apps.identity", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + } + err := config.Initialize(createYMLSnippet(cfgForSnippet)) + Expect(err).ToNot(HaveOccurred()) + err = config.Process() + Expect(err).ToNot(HaveOccurred()) + }) + + It("returns true for mTLS domain with port", func() { + Expect(config.IsMtlsDomain("xfcc-tester.apps.identity:443")).To(BeTrue()) + }) + + It("returns true for mTLS domain without port", func() { + Expect(config.IsMtlsDomain("xfcc-tester.apps.identity")).To(BeTrue()) + }) + + It("returns false for non-mTLS domain with port", func() { + Expect(config.IsMtlsDomain("other.example.com:443")).To(BeFalse()) + }) + + It("returns false for non-mTLS domain without port", func() { + Expect(config.IsMtlsDomain("other.example.com")).To(BeFalse()) + }) + + It("matches case-insensitively per RFC 1035", func() { + // DNS hostnames are case-insensitive + Expect(config.IsMtlsDomain("XFCC-TESTER.APPS.IDENTITY")).To(BeTrue()) + Expect(config.IsMtlsDomain("Xfcc-Tester.Apps.Identity")).To(BeTrue()) + Expect(config.IsMtlsDomain("xfcc-tester.APPS.identity")).To(BeTrue()) + }) + + It("matches case-insensitively with port", func() { + Expect(config.IsMtlsDomain("XFCC-TESTER.APPS.IDENTITY:443")).To(BeTrue()) + Expect(config.IsMtlsDomain("Xfcc-Tester.Apps.Identity:8443")).To(BeTrue()) + }) + }) + + Describe("processMtlsDomains validation", func() { + var certChain test_util.CertChain + + BeforeEach(func() { + certChain = test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + }) + + It("returns an error when xfcc_format is set with always_forward", func() { + cfgForSnippet.Domains = []MtlsDomainConfig{ + { + Domain: "*.apps.identity", + XFCCFormat: "envoy", + ForwardedClientCert: "always_forward", + CACerts: string(certChain.CACertPEM), + }, + } + err := config.Initialize(createYMLSnippet(cfgForSnippet)) + Expect(err).ToNot(HaveOccurred()) + err = config.Process() + Expect(err).To(MatchError(ContainSubstring("xfcc_format has no effect when forwarded_client_cert is 'always_forward'"))) + }) + + It("allows xfcc_format with sanitize_set", func() { + cfgForSnippet.Domains = []MtlsDomainConfig{ + { + Domain: "*.apps.identity", + XFCCFormat: "envoy", + ForwardedClientCert: "sanitize_set", + CACerts: string(certChain.CACertPEM), + }, + } + err := config.Initialize(createYMLSnippet(cfgForSnippet)) + Expect(err).ToNot(HaveOccurred()) + err = config.Process() + Expect(err).ToNot(HaveOccurred()) + }) + + It("allows raw xfcc_format with always_forward", func() { + cfgForSnippet.Domains = []MtlsDomainConfig{ + { + Domain: "*.apps.identity", + XFCCFormat: "raw", + ForwardedClientCert: "always_forward", + CACerts: string(certChain.CACertPEM), + }, + } + err := config.Initialize(createYMLSnippet(cfgForSnippet)) + Expect(err).ToNot(HaveOccurred()) + err = config.Process() + Expect(err).ToNot(HaveOccurred()) + }) + }) }) func baseConfigFixture() *Config { diff --git a/src/code.cloudfoundry.org/gorouter/handlers/access_log.go b/src/code.cloudfoundry.org/gorouter/handlers/access_log.go index 6d21296a4..88e9ad4c8 100644 --- a/src/code.cloudfoundry.org/gorouter/handlers/access_log.go +++ b/src/code.cloudfoundry.org/gorouter/handlers/access_log.go @@ -83,6 +83,17 @@ func (a *accessLog) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http alr.LocalAddress = reqInfo.LocalAddress + // Identity-aware routing authorization fields + if reqInfo.CallerIdentity != nil { + alr.CallerCFApp = reqInfo.CallerIdentity.AppGUID + alr.CallerCFSpace = reqInfo.CallerIdentity.SpaceGUID + alr.CallerCFOrg = reqInfo.CallerIdentity.OrgGUID + } + if reqInfo.AuthResult != nil { + alr.RoutePolicy = reqInfo.AuthResult.Rule + } + alr.TlsSNI = reqInfo.TlsSNI + a.accessLogger.Log(*alr) } diff --git a/src/code.cloudfoundry.org/gorouter/handlers/auth_error.go b/src/code.cloudfoundry.org/gorouter/handlers/auth_error.go new file mode 100644 index 000000000..9f15a5990 --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/auth_error.go @@ -0,0 +1,66 @@ +package handlers + +import ( + "fmt" + "net/http" +) + +// AuthError represents an authorization failure with structured metadata +// for logging and error responses. Used for both mTLS and future authentication +// methods like SPIFFE JWT tokens. +type AuthError struct { + // Rule is the authorization rule that failed (e.g., "domain:scope=org:post-selection") + Rule string + // Reason is a human-readable explanation of why authorization failed + Reason string + // HTTPStatus is the HTTP status code to return (typically 403 Forbidden) + HTTPStatus int +} + +func (e *AuthError) Error() string { + return fmt.Sprintf("authorization denied: %s (rule: %s)", e.Reason, e.Rule) +} + +// ClientMessage returns a generic error message safe for client responses. +// This prevents leaking internal rule names, app GUIDs, or authorization logic. +func (e *AuthError) ClientMessage() string { + // Return a generic message based on the HTTP status + switch e.HTTPStatus { + case http.StatusForbidden: + return "Forbidden" + case http.StatusMisdirectedRequest: + return "Misdirected Request" + default: + return http.StatusText(e.HTTPStatus) + } +} + +// NewAuthError creates a new authorization error with 403 Forbidden status +func NewAuthError(rule, reason string) *AuthError { + return &AuthError{ + Rule: rule, + Reason: reason, + HTTPStatus: http.StatusForbidden, + } +} + +// NewAuthErrorWithStatus creates a new authorization error with a custom HTTP status +func NewAuthErrorWithStatus(rule, reason string, status int) *AuthError { + return &AuthError{ + Rule: rule, + Reason: reason, + HTTPStatus: status, + } +} + +// AuthResult captures the outcome of identity-aware routing authorization. +// This is populated on RequestInfo and flows into access logs. +type AuthResult struct { + // Outcome is "allowed" or "denied"; empty if no authorization was performed. + Outcome string + // Rule identifies which rule matched or caused denial, e.g. + // "route:cf:app:", "domain:scope=org", "identity_extraction". + Rule string + // DeniedReason is a human-readable explanation for denial, empty on allow. + DeniedReason string +} diff --git a/src/code.cloudfoundry.org/gorouter/handlers/clientcert.go b/src/code.cloudfoundry.org/gorouter/handlers/clientcert.go index 437387f64..30b4bd67e 100644 --- a/src/code.cloudfoundry.org/gorouter/handlers/clientcert.go +++ b/src/code.cloudfoundry.org/gorouter/handlers/clientcert.go @@ -1,6 +1,10 @@ package handlers import ( + "crypto/sha256" + "crypto/x509" + "crypto/x509/pkix" + "encoding/hex" "encoding/pem" "errors" "fmt" @@ -22,6 +26,7 @@ type clientCert struct { skipSanitization func(req *http.Request) bool forceDeleteHeader func(req *http.Request) (bool, error) forwardingMode string + config *config.Config logger *slog.Logger errorWriter errorwriter.ErrorWriter } @@ -30,6 +35,7 @@ func NewClientCert( skipSanitization func(req *http.Request) bool, forceDeleteHeader func(req *http.Request) (bool, error), forwardingMode string, + cfg *config.Config, logger *slog.Logger, ew errorwriter.ErrorWriter, ) negroni.Handler { @@ -37,6 +43,7 @@ func NewClientCert( skipSanitization: skipSanitization, forceDeleteHeader: forceDeleteHeader, forwardingMode: forwardingMode, + config: cfg, logger: logger, errorWriter: ew, } @@ -45,8 +52,18 @@ func NewClientCert( func (c *clientCert) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { logger := LoggerWithTraceInfo(c.logger, r) skip := c.skipSanitization(r) + + // Determine forwarding mode and XFCC format - use domain-specific if on mTLS domain + forwardingMode := c.forwardingMode + xfccFormat := config.XFCC_FORMAT_RAW // Default for non-mTLS domains + mtlsDomainConfig := c.config.GetMtlsDomainConfig(r.Host) + if mtlsDomainConfig != nil { + forwardingMode = mtlsDomainConfig.ForwardedClientCert + xfccFormat = mtlsDomainConfig.XFCCFormat + } + if !skip { - switch c.forwardingMode { + switch forwardingMode { case config.FORWARD: if r.TLS == nil || len(r.TLS.PeerCertificates) == 0 { r.Header.Del(xfcc) @@ -54,7 +71,11 @@ func (c *clientCert) ServeHTTP(rw http.ResponseWriter, r *http.Request, next htt case config.SANITIZE_SET: r.Header.Del(xfcc) if r.TLS != nil { - replaceXFCCHeader(r) + if xfccFormat == config.XFCC_FORMAT_ENVOY { + replaceXFCCHeaderEnvoyFormat(r) + } else { + replaceXFCCHeader(r) + } } } } @@ -95,6 +116,67 @@ func replaceXFCCHeader(r *http.Request) { } } +// replaceXFCCHeaderEnvoyFormat sets the X-Forwarded-Client-Cert header using Envoy's +// compact format: Hash=;Subject="" +// This is significantly smaller than the raw certificate format (~300 bytes vs ~1.5KB) +func replaceXFCCHeaderEnvoyFormat(r *http.Request) { + if len(r.TLS.PeerCertificates) > 0 { + cert := r.TLS.PeerCertificates[0] + r.Header.Add(xfcc, formatXFCCEnvoy(cert)) + } +} + +// formatXFCCEnvoy generates the Envoy-style XFCC header value: +// Hash=;Subject="" +func formatXFCCEnvoy(cert *x509.Certificate) string { + // Calculate SHA-256 hash of the DER-encoded certificate + hash := sha256.Sum256(cert.Raw) + hashHex := hex.EncodeToString(hash[:]) + + // Format Subject DN using standard X.509 format + subject := formatSubjectDN(cert.Subject) + + return fmt.Sprintf("Hash=%s;Subject=\"%s\"", hashHex, subject) +} + +// formatSubjectDN formats an X.509 Distinguished Name in the standard format +// e.g., "CN=instance-id,OU=app:guid,OU=space:guid,OU=organization:guid" +func formatSubjectDN(name pkix.Name) string { + var parts []string + + // Add CN first (if present) + if name.CommonName != "" { + parts = append(parts, "CN="+name.CommonName) + } + + // Add OUs (preserve order from certificate) + for _, ou := range name.OrganizationalUnit { + parts = append(parts, "OU="+ou) + } + + // Add O (Organization) + for _, o := range name.Organization { + parts = append(parts, "O="+o) + } + + // Add L (Locality) + for _, l := range name.Locality { + parts = append(parts, "L="+l) + } + + // Add ST (State/Province) + for _, st := range name.Province { + parts = append(parts, "ST="+st) + } + + // Add C (Country) + for _, c := range name.Country { + parts = append(parts, "C="+c) + } + + return strings.Join(parts, ",") +} + func sanitize(cert []byte) string { s := string(cert) r := strings.NewReplacer("-----BEGIN CERTIFICATE-----", "", diff --git a/src/code.cloudfoundry.org/gorouter/handlers/clientcert_test.go b/src/code.cloudfoundry.org/gorouter/handlers/clientcert_test.go index f8caa1bdf..306a6caf4 100644 --- a/src/code.cloudfoundry.org/gorouter/handlers/clientcert_test.go +++ b/src/code.cloudfoundry.org/gorouter/handlers/clientcert_test.go @@ -45,7 +45,8 @@ var _ = Describe("Clientcert", func() { DescribeTable("Client Cert Error Handling", func(forceDeleteHeaderFunc func(*http.Request) (bool, error), skipSanitizationFunc func(*http.Request) bool, errorCase string) { logger = test_util.NewTestLogger("") - clientCertHandler := handlers.NewClientCert(skipSanitizationFunc, forceDeleteHeaderFunc, config.SANITIZE_SET, logger.Logger, errorWriter) + cfg, _ := config.DefaultConfig() + clientCertHandler := handlers.NewClientCert(skipSanitizationFunc, forceDeleteHeaderFunc, config.SANITIZE_SET, cfg, logger.Logger, errorWriter) nextHandlerWasCalled := false nextHandler := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { nextHandlerWasCalled = true }) @@ -82,7 +83,8 @@ var _ = Describe("Clientcert", func() { DescribeTable("Client Cert Result", func(forceDeleteHeaderFunc func(*http.Request) (bool, error), skipSanitizationFunc func(*http.Request) bool, forwardedClientCert string, noTLSCertStrip bool, TLSCertStrip bool, mTLSCertStrip string) { logger = test_util.NewTestLogger("test") - clientCertHandler := handlers.NewClientCert(skipSanitizationFunc, forceDeleteHeaderFunc, forwardedClientCert, logger.Logger, errorWriter) + cfg, _ := config.DefaultConfig() + clientCertHandler := handlers.NewClientCert(skipSanitizationFunc, forceDeleteHeaderFunc, forwardedClientCert, cfg, logger.Logger, errorWriter) nextReq := &http.Request{} nextHandler := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { nextReq = r }) @@ -209,3 +211,201 @@ func sanitize(cert []byte) string { "\n", "") return r.Replace(s) } + +var _ = Describe("Clientcert mTLS Domain XFCC Format", func() { + var ( + dontForceDeleteHeader = func(req *http.Request) (bool, error) { return false, nil } + dontSkipSanitization = func(req *http.Request) bool { return false } + errorWriter = errorwriter.NewPlaintextErrorWriter() + logger *test_util.TestLogger + ) + + Describe("Envoy XFCC Format", func() { + It("uses Envoy format when configured for mTLS domain", func() { + logger = test_util.NewTestLogger("test") + + // Create instance identity cert with Diego format OUs + certChain := test_util.CreateInstanceIdentityCert(test_util.InstanceIdentityCertNames{ + CommonName: "instance-id-123", + AppGUID: "app-guid-456", + SpaceGUID: "space-guid-789", + OrgGUID: "org-guid-abc", + }) + + // Configure mTLS domain with Envoy format + cfg, err := config.DefaultConfig() + Expect(err).NotTo(HaveOccurred()) + + cfg.Domains = []config.MtlsDomainConfig{{ + Domain: "*.apps.mtls.internal", + CACerts: string(certChain.CACertPEM), + ForwardedClientCert: config.SANITIZE_SET, + XFCCFormat: config.XFCC_FORMAT_ENVOY, + }} + err = cfg.Process() + Expect(err).NotTo(HaveOccurred()) + + clientCertHandler := handlers.NewClientCert(dontSkipSanitization, dontForceDeleteHeader, config.SANITIZE_SET, cfg, logger.Logger, errorWriter) + + var capturedXFCC string + nextHandler := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { + capturedXFCC = r.Header.Get("X-Forwarded-Client-Cert") + }) + + n := negroni.New() + n.Use(clientCertHandler) + n.UseHandlerFunc(nextHandler) + + // Setup mTLS test server + tlsCert, err := tls.X509KeyPair(certChain.CertPEM, certChain.PrivKeyPEM) + Expect(err).ToNot(HaveOccurred()) + + certPool := x509.NewCertPool() + certPool.AddCert(certChain.CACert) + + serverTLSConfig := &tls.Config{ + Certificates: []tls.Certificate{tlsCert}, + ClientCAs: certPool, + ClientAuth: tls.RequestClientCert, + } + + server := httptest.NewUnstartedServer(n) + server.TLS = serverTLSConfig + server.StartTLS() + defer server.Close() + + // Create client with mTLS cert + clientTLSConfig := &tls.Config{ + Certificates: []tls.Certificate{tlsCert}, + RootCAs: certPool, + InsecureSkipVerify: true, // Test server uses 127.0.0.1 which isn't in cert SANs + } + + transport := &http.Transport{TLSClientConfig: clientTLSConfig} + client := &http.Client{Transport: transport} + + // Make request to mTLS domain + req, err := http.NewRequest("GET", server.URL, nil) + Expect(err).NotTo(HaveOccurred()) + req.Host = "myapp.apps.mtls.internal" + + _, err = client.Do(req) + Expect(err).ToNot(HaveOccurred()) + + // Verify Envoy format: Hash=;Subject="" + Expect(capturedXFCC).To(HavePrefix("Hash=")) + Expect(capturedXFCC).To(ContainSubstring(";Subject=\"")) + + // Verify Subject contains OUs + Expect(capturedXFCC).To(ContainSubstring("OU=app:app-guid-456")) + Expect(capturedXFCC).To(ContainSubstring("OU=space:space-guid-789")) + Expect(capturedXFCC).To(ContainSubstring("OU=organization:org-guid-abc")) + Expect(capturedXFCC).To(ContainSubstring("CN=instance-id-123")) + + // Verify it doesn't contain base64-encoded cert (which would be much longer) + Expect(len(capturedXFCC)).To(BeNumerically("<", 500)) // Envoy format is ~300 bytes + }) + + It("uses raw format when configured for mTLS domain", func() { + logger = test_util.NewTestLogger("test") + + // Create instance identity cert + certChain := test_util.CreateInstanceIdentityCert(test_util.InstanceIdentityCertNames{ + CommonName: "instance-id-123", + AppGUID: "app-guid-456", + }) + + // Configure mTLS domain with raw format (default) + cfg, err := config.DefaultConfig() + Expect(err).NotTo(HaveOccurred()) + + cfg.Domains = []config.MtlsDomainConfig{{ + Domain: "*.apps.mtls.internal", + CACerts: string(certChain.CACertPEM), + ForwardedClientCert: config.SANITIZE_SET, + XFCCFormat: config.XFCC_FORMAT_RAW, + }} + err = cfg.Process() + Expect(err).NotTo(HaveOccurred()) + + clientCertHandler := handlers.NewClientCert(dontSkipSanitization, dontForceDeleteHeader, config.SANITIZE_SET, cfg, logger.Logger, errorWriter) + + var capturedXFCC string + nextHandler := http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { + capturedXFCC = r.Header.Get("X-Forwarded-Client-Cert") + }) + + n := negroni.New() + n.Use(clientCertHandler) + n.UseHandlerFunc(nextHandler) + + // Setup mTLS test server + tlsCert, err := tls.X509KeyPair(certChain.CertPEM, certChain.PrivKeyPEM) + Expect(err).ToNot(HaveOccurred()) + + certPool := x509.NewCertPool() + certPool.AddCert(certChain.CACert) + + serverTLSConfig := &tls.Config{ + Certificates: []tls.Certificate{tlsCert}, + ClientCAs: certPool, + ClientAuth: tls.RequestClientCert, + } + + server := httptest.NewUnstartedServer(n) + server.TLS = serverTLSConfig + server.StartTLS() + defer server.Close() + + // Create client with mTLS cert + clientTLSConfig := &tls.Config{ + Certificates: []tls.Certificate{tlsCert}, + RootCAs: certPool, + InsecureSkipVerify: true, // Test server uses 127.0.0.1 which isn't in cert SANs + } + + transport := &http.Transport{TLSClientConfig: clientTLSConfig} + client := &http.Client{Transport: transport} + + // Make request to mTLS domain + req, err := http.NewRequest("GET", server.URL, nil) + Expect(err).NotTo(HaveOccurred()) + req.Host = "myapp.apps.mtls.internal" + + _, err = client.Do(req) + Expect(err).ToNot(HaveOccurred()) + + // Verify raw format: base64-encoded certificate (no "Hash=" or "Subject=") + Expect(capturedXFCC).NotTo(HavePrefix("Hash=")) + Expect(capturedXFCC).NotTo(ContainSubstring("Subject=")) + + // Raw format is base64-encoded cert, much larger + Expect(len(capturedXFCC)).To(BeNumerically(">", 1000)) + }) + + It("defaults to raw format when xfcc_format is not specified", func() { + logger = test_util.NewTestLogger("test") + + certChain := test_util.CreateInstanceIdentityCert(test_util.InstanceIdentityCertNames{ + CommonName: "instance-id-123", + AppGUID: "app-guid-456", + }) + + // Configure mTLS domain without xfcc_format + cfg, err := config.DefaultConfig() + Expect(err).NotTo(HaveOccurred()) + + cfg.Domains = []config.MtlsDomainConfig{{ + Domain: "*.apps.mtls.internal", + CACerts: string(certChain.CACertPEM), + ForwardedClientCert: config.SANITIZE_SET, + // XFCCFormat not set - should default to "raw" + }} + err = cfg.Process() + Expect(err).NotTo(HaveOccurred()) + + // After Process(), XFCCFormat should be set to "raw" + Expect(cfg.Domains[0].XFCCFormat).To(Equal(config.XFCC_FORMAT_RAW)) + }) + }) +}) diff --git a/src/code.cloudfoundry.org/gorouter/handlers/fakes/fake_post_selection_handler.go b/src/code.cloudfoundry.org/gorouter/handlers/fakes/fake_post_selection_handler.go new file mode 100644 index 000000000..1054a36be --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/fakes/fake_post_selection_handler.go @@ -0,0 +1,112 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package fakes + +import ( + "sync" + + "code.cloudfoundry.org/gorouter/handlers" + "code.cloudfoundry.org/gorouter/route" +) + +type FakePostSelectionHandler struct { + CheckStub func(*route.Endpoint, *handlers.RequestInfo) error + checkMutex sync.RWMutex + checkArgsForCall []struct { + arg1 *route.Endpoint + arg2 *handlers.RequestInfo + } + checkReturns struct { + result1 error + } + checkReturnsOnCall map[int]struct { + result1 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakePostSelectionHandler) Check(arg1 *route.Endpoint, arg2 *handlers.RequestInfo) error { + fake.checkMutex.Lock() + ret, specificReturn := fake.checkReturnsOnCall[len(fake.checkArgsForCall)] + fake.checkArgsForCall = append(fake.checkArgsForCall, struct { + arg1 *route.Endpoint + arg2 *handlers.RequestInfo + }{arg1, arg2}) + stub := fake.CheckStub + fakeReturns := fake.checkReturns + fake.recordInvocation("Check", []interface{}{arg1, arg2}) + fake.checkMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakePostSelectionHandler) CheckCallCount() int { + fake.checkMutex.RLock() + defer fake.checkMutex.RUnlock() + return len(fake.checkArgsForCall) +} + +func (fake *FakePostSelectionHandler) CheckCalls(stub func(*route.Endpoint, *handlers.RequestInfo) error) { + fake.checkMutex.Lock() + defer fake.checkMutex.Unlock() + fake.CheckStub = stub +} + +func (fake *FakePostSelectionHandler) CheckArgsForCall(i int) (*route.Endpoint, *handlers.RequestInfo) { + fake.checkMutex.RLock() + defer fake.checkMutex.RUnlock() + argsForCall := fake.checkArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakePostSelectionHandler) CheckReturns(result1 error) { + fake.checkMutex.Lock() + defer fake.checkMutex.Unlock() + fake.CheckStub = nil + fake.checkReturns = struct { + result1 error + }{result1} +} + +func (fake *FakePostSelectionHandler) CheckReturnsOnCall(i int, result1 error) { + fake.checkMutex.Lock() + defer fake.checkMutex.Unlock() + fake.CheckStub = nil + if fake.checkReturnsOnCall == nil { + fake.checkReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.checkReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakePostSelectionHandler) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakePostSelectionHandler) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ handlers.PostSelectionHandler = new(FakePostSelectionHandler) diff --git a/src/code.cloudfoundry.org/gorouter/handlers/identity.go b/src/code.cloudfoundry.org/gorouter/handlers/identity.go new file mode 100644 index 000000000..a3ec3f5ca --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/identity.go @@ -0,0 +1,222 @@ +package handlers + +import ( + "crypto/x509" + "encoding/base64" + "errors" + "fmt" + "net/http" + "strings" + + "code.cloudfoundry.org/gorouter/config" + "github.com/urfave/negroni/v3" +) + +// CallerIdentity represents the identity of the calling application extracted from mTLS +// certificate. The certificate OU field contains: +// - app: for the application GUID +// - space: for the space GUID +// - organization: for the organization GUID +type CallerIdentity struct { + AppGUID string + SpaceGUID string + OrgGUID string +} + +// cfIdentityHandler extracts the caller identity from the X-Forwarded-Client-Cert header +// on mTLS domains. It parses CF app instance identity certificates (which encode +// app/space/org GUIDs in the Subject OU field). The identity is stored in the +// RequestInfo context for use by authorization handlers. +// +// Security: This handler only extracts identity when: +// 1. TLS was used for the connection +// 2. The request is for a configured mTLS domain +// This prevents spoofing of identity values via crafted XFCC headers on non-mTLS routes. +type cfIdentityHandler struct { + config *config.Config +} + +// NewCfIdentity creates a new CF app identity extraction handler. +// Returns NoopHandler when no mTLS domains are configured. +func NewCfIdentity(cfg *config.Config) negroni.Handler { + if len(cfg.Domains) == 0 { + return NoopHandler + } + return &cfIdentityHandler{config: cfg} +} + +func (h *cfIdentityHandler) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + // Only extract identity when TLS was used + if r.TLS == nil { + next(w, r) + return + } + + // Only extract identity on mTLS domains + hostDomain := hostWithoutPort(r.Host) + domainConfig := h.config.GetMtlsDomainConfig(hostDomain) + if domainConfig == nil { + next(w, r) + return + } + + reqInfo, err := ContextRequestInfo(r) + if err != nil { + next(w, r) + return + } + + // Extract identity from X-Forwarded-Client-Cert header using the configured format + xfccHeader := r.Header.Get("X-Forwarded-Client-Cert") + if xfccHeader != "" { + identity, err := extractIdentityFromXFCC(xfccHeader, domainConfig.XFCCFormat) + if err == nil { + reqInfo.CallerIdentity = identity + } + // If extraction fails, continue without setting identity + // The authorization handler will deny access if identity is required + } + + next(w, r) +} + +// extractIdentityFromXFCC parses the X-Forwarded-Client-Cert header and extracts +// the application, space, and organization GUIDs from the client certificate's +// OU (Organizational Unit) field. +// +// The format parameter determines how the XFCC header is parsed: +// - "envoy": Parses Hash=;Subject="" format, extracting OUs from the Subject DN +// - "raw": Decodes raw base64 certificate (produced by clientcert.go sanitize()) +// +// Expected OU formats: +// - "app:" +// - "space:" +// - "organization:" +func extractIdentityFromXFCC(xfcc string, format string) (*CallerIdentity, error) { + switch format { + case config.XFCC_FORMAT_ENVOY: + return extractIdentityFromEnvoyXFCC(xfcc) + default: + // "raw" format: base64-encoded DER certificate + return extractIdentityFromRawXFCC(xfcc) + } +} + +// extractIdentityFromEnvoyXFCC parses the envoy compact format: +// Hash=;Subject="" +func extractIdentityFromEnvoyXFCC(xfcc string) (*CallerIdentity, error) { + // Parse Subject="" field + subjectStart := strings.Index(xfcc, "Subject=\"") + if subjectStart == -1 { + return nil, errors.New("envoy format XFCC missing Subject field") + } + subjectStart += len("Subject=\"") + subjectEnd := strings.Index(xfcc[subjectStart:], "\"") + if subjectEnd == -1 { + return nil, errors.New("malformed Subject field in XFCC header") + } + if subjectEnd == 0 { + return nil, errors.New("empty Subject field in XFCC header") + } + subjectDN := xfcc[subjectStart : subjectStart+subjectEnd] + return extractIdentityFromSubjectDN(subjectDN) +} + +// extractIdentityFromRawXFCC parses raw base64 format (no PEM markers) +// produced by clientcert.go sanitize() +func extractIdentityFromRawXFCC(xfcc string) (*CallerIdentity, error) { + certDER, err := base64.StdEncoding.DecodeString(strings.TrimSpace(xfcc)) + if err != nil { + return nil, errors.New("failed to decode base64 certificate: " + err.Error()) + } + + cert, err := x509.ParseCertificate(certDER) + if err != nil { + return nil, err + } + + return extractIdentityFromCert(cert) +} + +// extractIdentityFromSubjectDN parses a Subject DN string and extracts GUIDs +// DN format: "CN=instance-id,OU=app:guid,OU=space:guid,OU=organization:guid" +func extractIdentityFromSubjectDN(subjectDN string) (*CallerIdentity, error) { + identity := &CallerIdentity{} + + // Split DN into RDNs (Relative Distinguished Names) + // Handle both comma and slash separators + var rdns []string + if strings.Contains(subjectDN, ",") { + rdns = strings.Split(subjectDN, ",") + } else if strings.Contains(subjectDN, "/") { + // Some formats use "/" as separator + rdns = strings.Split(subjectDN, "/") + } else { + return nil, fmt.Errorf("unrecognized DN format: %q", subjectDN) + } + + for _, rdn := range rdns { + rdn = strings.TrimSpace(rdn) + if rdn == "" { + continue + } + + // Parse OU fields + if strings.HasPrefix(rdn, "OU=") { + ouValue := strings.TrimPrefix(rdn, "OU=") + if strings.HasPrefix(ouValue, "app:") { + appGUID := strings.TrimPrefix(ouValue, "app:") + if appGUID != "" { + identity.AppGUID = appGUID + } + } else if strings.HasPrefix(ouValue, "space:") { + spaceGUID := strings.TrimPrefix(ouValue, "space:") + if spaceGUID != "" { + identity.SpaceGUID = spaceGUID + } + } else if strings.HasPrefix(ouValue, "organization:") { + orgGUID := strings.TrimPrefix(ouValue, "organization:") + if orgGUID != "" { + identity.OrgGUID = orgGUID + } + } + } + } + + // At minimum, require app GUID to be present + if identity.AppGUID == "" { + return nil, errors.New("no app GUID found in Subject DN") + } + + return identity, nil +} + +// extractIdentityFromCert extracts GUIDs from an X.509 certificate's OU fields +func extractIdentityFromCert(cert *x509.Certificate) (*CallerIdentity, error) { + identity := &CallerIdentity{} + for _, ou := range cert.Subject.OrganizationalUnit { + if strings.HasPrefix(ou, "app:") { + appGUID := strings.TrimPrefix(ou, "app:") + if appGUID != "" { + identity.AppGUID = appGUID + } + } else if strings.HasPrefix(ou, "space:") { + spaceGUID := strings.TrimPrefix(ou, "space:") + if spaceGUID != "" { + identity.SpaceGUID = spaceGUID + } + } else if strings.HasPrefix(ou, "organization:") { + orgGUID := strings.TrimPrefix(ou, "organization:") + if orgGUID != "" { + identity.OrgGUID = orgGUID + } + } + } + + // At minimum, require app GUID to be present + if identity.AppGUID == "" { + return nil, errors.New("no app GUID found in certificate OU") + } + + return identity, nil +} diff --git a/src/code.cloudfoundry.org/gorouter/handlers/identity_test.go b/src/code.cloudfoundry.org/gorouter/handlers/identity_test.go new file mode 100644 index 000000000..14feb5453 --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/identity_test.go @@ -0,0 +1,393 @@ +package handlers_test + +import ( + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/base64" + "math/big" + "net/http" + "net/http/httptest" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/urfave/negroni/v3" + + "code.cloudfoundry.org/gorouter/config" + "code.cloudfoundry.org/gorouter/handlers" + "code.cloudfoundry.org/gorouter/test_util" +) + +var _ = Describe("CfIdentity", func() { + var ( + handler negroni.Handler + cfg *config.Config + nextCalled bool + nextHandler http.HandlerFunc + recorder *httptest.ResponseRecorder + request *http.Request + requestInfo *handlers.RequestInfo + ) + + BeforeEach(func() { + cfg, _ = config.DefaultConfig() + certChain := test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.identity", + XFCCFormat: "raw", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "envoy.apps.identity", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + } + err := cfg.Process() + Expect(err).ToNot(HaveOccurred()) + + handler = handlers.NewCfIdentity(cfg) + nextCalled = false + recorder = httptest.NewRecorder() + + nextHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + nextCalled = true + request = r + }) + + request = test_util.NewRequest("GET", "backend.apps.identity", "/", nil) + request.TLS = &tls.ConnectionState{} + }) + + Context("when TLS is not used", func() { + BeforeEach(func() { + request.TLS = nil + cert := generateTestCert("app:should-not-extract") + request.Header.Set("X-Forwarded-Client-Cert", buildGoRouterXFCCHeader(cert)) + }) + + It("skips identity extraction and calls next", func() { + handler.ServeHTTP(recorder, request, nextHandler) + Expect(nextCalled).To(BeTrue()) + }) + }) + + Context("when host is not an mTLS domain", func() { + BeforeEach(func() { + request = test_util.NewRequest("GET", "regular.example.com", "/", nil) + request.TLS = &tls.ConnectionState{} + cert := generateTestCert("app:should-not-extract") + request.Header.Set("X-Forwarded-Client-Cert", buildGoRouterXFCCHeader(cert)) + }) + + It("skips identity extraction and calls next", func() { + handler.ServeHTTP(recorder, request, nextHandler) + Expect(nextCalled).To(BeTrue()) + }) + }) + + Context("when RequestInfo is not in context", func() { + It("calls next handler without setting identity", func() { + handler.ServeHTTP(recorder, request, nextHandler) + + Expect(nextCalled).To(BeTrue()) + Expect(recorder.Code).To(Equal(http.StatusOK)) + }) + }) + + Context("when RequestInfo is in context", func() { + var runHandler = func() { + reqInfoHandler := handlers.NewRequestInfo() + n := negroni.New() + n.Use(reqInfoHandler) + n.Use(handler) + n.UseHandlerFunc(func(w http.ResponseWriter, r *http.Request) { + nextCalled = true + request = r + var err error + requestInfo, err = handlers.ContextRequestInfo(r) + Expect(err).NotTo(HaveOccurred()) + }) + + n.ServeHTTP(recorder, request) + } + + Context("when X-Forwarded-Client-Cert header is not present", func() { + It("calls next handler without setting identity", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).To(BeNil()) + }) + }) + + Context("with raw format (*.apps.identity domain)", func() { + Context("with valid cert containing app GUID in OU", func() { + BeforeEach(func() { + cert := generateTestCert("app:test-app-guid-123") + request.Header.Set("X-Forwarded-Client-Cert", buildGoRouterXFCCHeader(cert)) + }) + + It("extracts caller identity with app GUID", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).NotTo(BeNil()) + Expect(requestInfo.CallerIdentity.AppGUID).To(Equal("test-app-guid-123")) + }) + }) + + Context("with cert containing multiple OUs", func() { + BeforeEach(func() { + cert := generateTestCertWithMultipleOUs([]string{ + "app:another-app-guid", + "space:test-space", + "organization:test-org", + }) + request.Header.Set("X-Forwarded-Client-Cert", buildGoRouterXFCCHeader(cert)) + }) + + It("extracts all GUIDs", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).NotTo(BeNil()) + Expect(requestInfo.CallerIdentity.AppGUID).To(Equal("another-app-guid")) + Expect(requestInfo.CallerIdentity.SpaceGUID).To(Equal("test-space")) + Expect(requestInfo.CallerIdentity.OrgGUID).To(Equal("test-org")) + }) + }) + + Context("with invalid base64 data", func() { + BeforeEach(func() { + request.Header.Set("X-Forwarded-Client-Cert", "not-valid-base64!!!") + }) + + It("does not set caller identity", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).To(BeNil()) + }) + }) + + Context("with valid base64 but invalid certificate data", func() { + BeforeEach(func() { + request.Header.Set("X-Forwarded-Client-Cert", base64.StdEncoding.EncodeToString([]byte("not a cert"))) + }) + + It("does not set caller identity", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).To(BeNil()) + }) + }) + + Context("with cert missing app GUID in OU", func() { + BeforeEach(func() { + cert := generateTestCertWithMultipleOUs([]string{"space:some-space"}) + request.Header.Set("X-Forwarded-Client-Cert", buildGoRouterXFCCHeader(cert)) + }) + + It("does not set caller identity", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).To(BeNil()) + }) + }) + + Context("with cert having empty app GUID", func() { + BeforeEach(func() { + cert := generateTestCert("app:") + request.Header.Set("X-Forwarded-Client-Cert", buildGoRouterXFCCHeader(cert)) + }) + + It("does not set caller identity", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).To(BeNil()) + }) + }) + }) + + Context("with envoy format (envoy.apps.identity domain)", func() { + BeforeEach(func() { + request = test_util.NewRequest("GET", "envoy.apps.identity", "/", nil) + request.TLS = &tls.ConnectionState{} + }) + + Context("with comma-separated DN format", func() { + BeforeEach(func() { + xfccHeader := `Hash=abc123;Subject="CN=instance-id,OU=app:envoy-app-guid,OU=space:envoy-space-guid,OU=organization:envoy-org-guid"` + request.Header.Set("X-Forwarded-Client-Cert", xfccHeader) + }) + + It("extracts all GUIDs from Subject DN", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).NotTo(BeNil()) + Expect(requestInfo.CallerIdentity.AppGUID).To(Equal("envoy-app-guid")) + Expect(requestInfo.CallerIdentity.SpaceGUID).To(Equal("envoy-space-guid")) + Expect(requestInfo.CallerIdentity.OrgGUID).To(Equal("envoy-org-guid")) + }) + }) + + Context("with slash-separated DN format", func() { + BeforeEach(func() { + xfccHeader := `Hash=abc123;Subject="/CN=instance-id/OU=app:slash-app-guid/OU=space:slash-space-guid/OU=organization:slash-org-guid"` + request.Header.Set("X-Forwarded-Client-Cert", xfccHeader) + }) + + It("extracts all GUIDs from Subject DN", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).NotTo(BeNil()) + Expect(requestInfo.CallerIdentity.AppGUID).To(Equal("slash-app-guid")) + Expect(requestInfo.CallerIdentity.SpaceGUID).To(Equal("slash-space-guid")) + Expect(requestInfo.CallerIdentity.OrgGUID).To(Equal("slash-org-guid")) + }) + }) + + Context("with only app GUID in Subject", func() { + BeforeEach(func() { + xfccHeader := `Hash=def456;Subject="CN=instance,OU=app:only-app-guid"` + request.Header.Set("X-Forwarded-Client-Cert", xfccHeader) + }) + + It("extracts app GUID", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).NotTo(BeNil()) + Expect(requestInfo.CallerIdentity.AppGUID).To(Equal("only-app-guid")) + Expect(requestInfo.CallerIdentity.SpaceGUID).To(Equal("")) + Expect(requestInfo.CallerIdentity.OrgGUID).To(Equal("")) + }) + }) + + Context("with Subject but no app GUID", func() { + BeforeEach(func() { + xfccHeader := `Hash=ghi789;Subject="CN=instance,OU=space:some-space,OU=organization:some-org"` + request.Header.Set("X-Forwarded-Client-Cert", xfccHeader) + }) + + It("does not set caller identity (app GUID required)", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).To(BeNil()) + }) + }) + + Context("with missing Subject field", func() { + BeforeEach(func() { + xfccHeader := `Hash=jkl012;Cert="some-pem-data"` + request.Header.Set("X-Forwarded-Client-Cert", xfccHeader) + }) + + It("does not set caller identity", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).To(BeNil()) + }) + }) + + Context("with malformed Subject field (missing closing quote)", func() { + BeforeEach(func() { + xfccHeader := `Hash=jkl012;Subject="CN=instance,OU=app:test-app` + request.Header.Set("X-Forwarded-Client-Cert", xfccHeader) + }) + + It("does not set caller identity", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).To(BeNil()) + }) + }) + + Context("with empty Subject", func() { + BeforeEach(func() { + xfccHeader := `Hash=mno345;Subject=""` + request.Header.Set("X-Forwarded-Client-Cert", xfccHeader) + }) + + It("does not set caller identity", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).To(BeNil()) + }) + }) + + Context("with Subject containing extra whitespace", func() { + BeforeEach(func() { + xfccHeader := `Hash=pqr678;Subject="CN=instance, OU=app:whitespace-app-guid, OU=space:whitespace-space-guid"` + request.Header.Set("X-Forwarded-Client-Cert", xfccHeader) + }) + + It("trims whitespace and extracts GUIDs", func() { + runHandler() + Expect(nextCalled).To(BeTrue()) + Expect(requestInfo.CallerIdentity).NotTo(BeNil()) + Expect(requestInfo.CallerIdentity.AppGUID).To(Equal("whitespace-app-guid")) + Expect(requestInfo.CallerIdentity.SpaceGUID).To(Equal("whitespace-space-guid")) + }) + }) + }) + }) + + Describe("NewCfIdentity", func() { + Context("when no mTLS domains are configured", func() { + It("returns NoopHandler", func() { + emptyCfg, _ := config.DefaultConfig() + Expect(emptyCfg.Domains).To(BeEmpty()) + + handler := handlers.NewCfIdentity(emptyCfg) + Expect(handler).To(BeIdenticalTo(handlers.NoopHandler)) + }) + }) + + Context("when mTLS domains are configured", func() { + It("returns a real handler", func() { + // cfg is already configured with domains in BeforeEach + handler := handlers.NewCfIdentity(cfg) + Expect(handler).NotTo(BeIdenticalTo(handlers.NoopHandler)) + }) + }) + }) +}) + +// Helper functions for generating test certificates + +func generateTestCert(ou string) *x509.Certificate { + return generateTestCertWithMultipleOUs([]string{ou}) +} + +func generateTestCertWithMultipleOUs(ous []string) *x509.Certificate { + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + Expect(err).NotTo(HaveOccurred()) + + template := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "test-instance", + OrganizationalUnit: ous, + }, + NotBefore: time.Now(), + NotAfter: time.Now().Add(24 * time.Hour), + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + } + + certDER, err := x509.CreateCertificate(rand.Reader, template, template, &privateKey.PublicKey, privateKey) + Expect(err).NotTo(HaveOccurred()) + + cert, err := x509.ParseCertificate(certDER) + Expect(err).NotTo(HaveOccurred()) + + return cert +} + +// buildGoRouterXFCCHeader produces the format that GoRouter's clientcert.go uses: +// raw base64 without PEM markers (produced by sanitize() function) +func buildGoRouterXFCCHeader(cert *x509.Certificate) string { + return base64.StdEncoding.EncodeToString(cert.Raw) +} diff --git a/src/code.cloudfoundry.org/gorouter/handlers/mtls_pre_auth.go b/src/code.cloudfoundry.org/gorouter/handlers/mtls_pre_auth.go new file mode 100644 index 000000000..c5f14a01d --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/mtls_pre_auth.go @@ -0,0 +1,103 @@ +package handlers + +import ( + "log/slog" + "net/http" + + "code.cloudfoundry.org/gorouter/config" + "code.cloudfoundry.org/gorouter/route" + "github.com/urfave/negroni/v3" +) + +// mtlsPreAuth performs pre-selection mTLS authorization checks that require +// caller identity to be available. It MUST run AFTER CfIdentity in the handler +// chain (which extracts CallerIdentity from the XFCC header). +// +// Checks performed: +// - Route pool existence (404 Not Found) +// - Route policy scope enforcement (403 Forbidden if identity missing) +// +// SNI/Host validation (421) is handled by MtlsSniCheck which runs earlier. +// Scope and route policies checking are performed post-selection. +type mtlsPreAuth struct { + config *config.Config + logger *slog.Logger +} + +// NewMtlsPreAuth creates a new pre-selection mTLS authorization handler. +// This handler MUST be placed after CfIdentity in the handler chain. +// Returns NoopHandler when no mTLS domains are configured. +func NewMtlsPreAuth(cfg *config.Config, logger *slog.Logger) negroni.Handler { + if len(cfg.Domains) == 0 { + return NoopHandler + } + return &mtlsPreAuth{ + config: cfg, + logger: logger, + } +} + +// setRouteEndpointForAccessLog sets the RouteEndpoint on reqInfo so that access +// logs are emitted to the target app even when the request is denied before the +// proxy has a chance to select an endpoint. +func setRouteEndpointForAccessLog(reqInfo *RequestInfo, pool *route.EndpointPool, logger *slog.Logger) { + if pool == nil || reqInfo.RouteEndpoint != nil { + return + } + iter := pool.Endpoints(logger, "", false, route.RoutingProperties{}) + if endpoint := iter.Next(0); endpoint != nil { + reqInfo.RouteEndpoint = endpoint + } +} + +func (h *mtlsPreAuth) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + reqInfo, err := ContextRequestInfo(r) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + hostDomain := hostWithoutPort(r.Host) + + // Only apply to mTLS domains + if !h.config.IsMtlsDomain(hostDomain) { + next(w, r) + return + } + + // ── Layer 1: Route lookup ────────────────────────────────────────────────── + if reqInfo.RoutePool == nil || reqInfo.RoutePool.IsEmpty() { + w.WriteHeader(http.StatusNotFound) + return + } + + pool := reqInfo.RoutePool + + // ── Layer 2: Route policy scope — is enforcement active? ─────────────────── + // Cloud Controller sets route_policy_scope in route options when the domain + // was created with --enforce-route-policies. An empty scope means "no + // enforcement": the route is on an mTLS domain but authorization is handled + // by the backend. + routePolicyScope := pool.RoutePolicyScope() + if routePolicyScope == "" { + // No enforcement — forward without authorization checks. + next(w, r) + return + } + + // Enforcement is active — we need caller identity for all checks below. + if reqInfo.CallerIdentity == nil { + setRouteEndpointForAccessLog(reqInfo, pool, h.logger) + reqInfo.AuthResult = &AuthResult{ + Outcome: "denied", + Rule: "identity_extraction", + DeniedReason: "certificate does not contain CF identity OU fields", + } + w.WriteHeader(http.StatusForbidden) + return + } + + // Pre-auth checks passed — continue to proxy (scope and route policies will be + // checked post-selection in the round tripper). + next(w, r) +} diff --git a/src/code.cloudfoundry.org/gorouter/handlers/mtls_pre_auth_test.go b/src/code.cloudfoundry.org/gorouter/handlers/mtls_pre_auth_test.go new file mode 100644 index 000000000..0a7cfb54c --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/mtls_pre_auth_test.go @@ -0,0 +1,254 @@ +package handlers_test + +import ( + "context" + "net/http" + "net/http/httptest" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/urfave/negroni/v3" + + "code.cloudfoundry.org/gorouter/config" + "code.cloudfoundry.org/gorouter/handlers" + "code.cloudfoundry.org/gorouter/route" + "code.cloudfoundry.org/gorouter/test_util" +) + +var _ = Describe("MtlsPreAuth", func() { + var ( + handler negroni.Handler + cfg *config.Config + req *http.Request + resp *httptest.ResponseRecorder + reqInfo *handlers.RequestInfo + nextCalled bool + ) + + BeforeEach(func() { + logger := test_util.NewTestLogger("mtls-pre-auth") + cfg, _ = config.DefaultConfig() + + // Configure mTLS domains + certChain := test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.identity", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "exact.mtls.domain", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + } + err := cfg.Process() + Expect(err).ToNot(HaveOccurred()) + + handler = handlers.NewMtlsPreAuth(cfg, logger.Logger) + + req = test_util.NewRequest("GET", "backend.apps.identity", "/", nil) + req.Host = "backend.apps.identity" + resp = httptest.NewRecorder() + reqInfo = &handlers.RequestInfo{} + + // Add RequestInfo to context + ctx := context.WithValue(req.Context(), handlers.RequestInfoCtxKey, reqInfo) + req = req.WithContext(ctx) + + nextCalled = false + }) + + nextHandler := func() http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + nextCalled = true + w.WriteHeader(http.StatusOK) + }) + } + + createPool := func(ep *route.Endpoint) *route.EndpointPool { + p := route.NewPool(&route.PoolOpts{ + Host: "backend.apps.identity", + }) + p.Put(ep) + return p + } + + Describe("ServeHTTP", func() { + Context("non-mTLS domain", func() { + It("passes through for non-mTLS domains", func() { + req.Host = "regular.example.com" + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeTrue()) + Expect(resp.Code).To(Equal(http.StatusOK)) + }) + }) + + Context("Layer 1: Route lookup", func() { + It("returns 404 when RoutePool is nil", func() { + reqInfo.RoutePool = nil + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeFalse()) + Expect(resp.Code).To(Equal(http.StatusNotFound)) + }) + + It("returns 404 when RoutePool is empty", func() { + emptyPool := route.NewPool(&route.PoolOpts{Host: "backend.apps.identity"}) + reqInfo.RoutePool = emptyPool + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeFalse()) + Expect(resp.Code).To(Equal(http.StatusNotFound)) + }) + }) + + Context("Layer 2: Route policy scope check", func() { + var endpoint *route.Endpoint + + It("passes through when RoutePolicyScope is empty (no enforcement)", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: "", // No enforcement + }) + reqInfo.RoutePool = createPool(endpoint) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeTrue()) + Expect(resp.Code).To(Equal(http.StatusOK)) + }) + + It("passes through when RoutePolicyScope is empty even without CallerIdentity", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: "", // No enforcement + }) + reqInfo.RoutePool = createPool(endpoint) + reqInfo.CallerIdentity = nil + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeTrue()) + Expect(resp.Code).To(Equal(http.StatusOK)) + }) + }) + + Context("Identity extraction requirement check", func() { + var endpoint *route.Endpoint + + It("returns 403 when CallerIdentity is nil and enforcement is active", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + reqInfo.RoutePool = createPool(endpoint) + reqInfo.CallerIdentity = nil + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeFalse()) + Expect(resp.Code).To(Equal(http.StatusForbidden)) + }) + + It("sets AuthResult when denying due to missing identity", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + reqInfo.RoutePool = createPool(endpoint) + reqInfo.CallerIdentity = nil + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(reqInfo.AuthResult).ToNot(BeNil()) + Expect(reqInfo.AuthResult.Outcome).To(Equal("denied")) + Expect(reqInfo.AuthResult.Rule).To(Equal("identity_extraction")) + Expect(reqInfo.AuthResult.DeniedReason).To(Equal("certificate does not contain CF identity OU fields")) + }) + + It("sets RouteEndpoint for access log when denying due to missing identity", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + reqInfo.RoutePool = createPool(endpoint) + reqInfo.CallerIdentity = nil + reqInfo.RouteEndpoint = nil + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(reqInfo.RouteEndpoint).ToNot(BeNil()) + Expect(reqInfo.RouteEndpoint.ApplicationId).To(Equal("backend-app")) + }) + + It("passes when CallerIdentity is present and enforcement is active", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + reqInfo.RoutePool = createPool(endpoint) + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "caller-space", + OrgGUID: "caller-org", + } + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeTrue()) + Expect(resp.Code).To(Equal(http.StatusOK)) + }) + }) + + Context("when RequestInfo is missing from context", func() { + It("returns 500", func() { + req = test_util.NewRequest("GET", "backend.apps.identity", "/", nil) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeFalse()) + Expect(resp.Code).To(Equal(http.StatusInternalServerError)) + }) + }) + }) + + Describe("NewMtlsPreAuth", func() { + Context("when no mTLS domains are configured", func() { + It("returns NoopHandler", func() { + logger := test_util.NewTestLogger("test") + emptyCfg, _ := config.DefaultConfig() + Expect(emptyCfg.Domains).To(BeEmpty()) + + handler := handlers.NewMtlsPreAuth(emptyCfg, logger.Logger) + Expect(handler).To(BeIdenticalTo(handlers.NoopHandler)) + }) + }) + + Context("when mTLS domains are configured", func() { + It("returns a real handler", func() { + logger := test_util.NewTestLogger("test") + // cfg is already configured with domains in BeforeEach + handler := handlers.NewMtlsPreAuth(cfg, logger.Logger) + Expect(handler).NotTo(BeIdenticalTo(handlers.NoopHandler)) + }) + }) + }) +}) diff --git a/src/code.cloudfoundry.org/gorouter/handlers/mtls_route_policies_auth.go b/src/code.cloudfoundry.org/gorouter/handlers/mtls_route_policies_auth.go new file mode 100644 index 000000000..24d1c2ba6 --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/mtls_route_policies_auth.go @@ -0,0 +1,124 @@ +package handlers + +import ( + "fmt" + "log/slog" + "strings" + + "code.cloudfoundry.org/gorouter/config" + "code.cloudfoundry.org/gorouter/route" +) + +// MtlsRoutePoliciesAuth performs post-selection route-level route policies authorization. +// It evaluates route policies (cf:app:, cf:space:, cf:org:, cf:any) against the +// caller's identity after endpoint selection. +// +// Route policies provide fine-grained per-route authorization beyond domain-level +// scope enforcement. This handler runs in the post-selection pipeline. +type MtlsRoutePoliciesAuth struct { + logger *slog.Logger +} + +// NewMtlsRoutePoliciesAuth creates a new post-selection route policies authorization handler. +// Returns NoopPostSelectionHandler when no mTLS domains are configured. +func NewMtlsRoutePoliciesAuth(cfg *config.Config, logger *slog.Logger) PostSelectionHandler { + if len(cfg.Domains) == 0 { + return NoopPostSelectionHandler + } + return &MtlsRoutePoliciesAuth{ + logger: logger, + } +} + +// evaluateRoutePolicies checks whether the caller identity satisfies any of the +// route policies. Policies use the source syntax from the RFC: +// +// cf:any — allow any authenticated caller +// cf:app: — allow a specific app +// cf:space: — allow all apps in a space +// cf:org: — allow all apps in an org +// +// Returns the matched source string and true on success; empty string and false +// if no policy matches. +func evaluateRoutePolicies(policies []string, identity *CallerIdentity) (string, bool) { + for _, policy := range policies { + policy = strings.TrimSpace(policy) + switch { + case policy == "cf:any": + return policy, true + case strings.HasPrefix(policy, "cf:app:"): + guid := strings.TrimPrefix(policy, "cf:app:") + if guid != "" && guid == identity.AppGUID { + return policy, true + } + case strings.HasPrefix(policy, "cf:space:"): + guid := strings.TrimPrefix(policy, "cf:space:") + if guid != "" && guid == identity.SpaceGUID { + return policy, true + } + case strings.HasPrefix(policy, "cf:org:"): + guid := strings.TrimPrefix(policy, "cf:org:") + if guid != "" && guid == identity.OrgGUID { + return policy, true + } + } + } + return "", false +} + +// Check performs post-selection route policies authorization. +// Returns nil if authorized, or an AuthError if no route policy matches +// the caller's identity. +func (h *MtlsRoutePoliciesAuth) Check(endpoint *route.Endpoint, reqInfo *RequestInfo) error { + // Get route policy scope from pool + if reqInfo.RoutePool == nil { + // This should not happen in normal operation, but if it does, + // we must deny the request to avoid authorization bypass + return NewAuthError("internal_error", "route pool missing during authorization") + } + + routePolicyScope := reqInfo.RoutePool.RoutePolicyScope() + if routePolicyScope == "" { + return nil // No route policy enforcement configured + } + + // Route policy enforcement requires caller identity + if reqInfo.CallerIdentity == nil { + // Defense in depth: identity should have been checked in pre-auth, + // but explicitly deny here to avoid silent authorization bypass + return NewAuthError( + "route:no_caller_identity", + "no caller identity present", + ) + } + + // Get route policies from the selected endpoint (per-endpoint authorization) + routePolicies := endpoint.RoutePolicies + if len(routePolicies) == 0 { + // Default deny: mTLS domain with enforcement enabled but no policies configured + return NewAuthError( + "route:no_route_policies", + "route has no route policies configured", + ) + } + + // Evaluate route policies + identity := reqInfo.CallerIdentity + matchedPolicy, allowed := evaluateRoutePolicies(routePolicies, identity) + + if !allowed { + return NewAuthError( + "route:route_policies", + fmt.Sprintf("caller app %s not in route_policies", identity.AppGUID), + ) + } + + // Route policy matched - populate reqInfo for RTR logs + if reqInfo.AuthResult == nil { + reqInfo.AuthResult = &AuthResult{} + } + reqInfo.AuthResult.Outcome = "allowed" + reqInfo.AuthResult.Rule = "route:" + matchedPolicy + + return nil +} diff --git a/src/code.cloudfoundry.org/gorouter/handlers/mtls_route_policies_auth_test.go b/src/code.cloudfoundry.org/gorouter/handlers/mtls_route_policies_auth_test.go new file mode 100644 index 000000000..3ecc22eb4 --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/mtls_route_policies_auth_test.go @@ -0,0 +1,577 @@ +package handlers_test + +import ( + "net/http" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "code.cloudfoundry.org/gorouter/config" + "code.cloudfoundry.org/gorouter/handlers" + "code.cloudfoundry.org/gorouter/route" + "code.cloudfoundry.org/gorouter/test_util" +) + +var _ = Describe("MtlsRoutePoliciesAuth", func() { + var ( + handler handlers.PostSelectionHandler + endpoint *route.Endpoint + reqInfo *handlers.RequestInfo + pool *route.EndpointPool + cfg *config.Config + ) + + BeforeEach(func() { + logger := test_util.NewTestLogger("mtls-route-policies-auth") + cfg, _ = config.DefaultConfig() + // Configure a domain so the handler is active + certChain := test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.mtls.internal", + CACerts: string(certChain.CACertPEM), + }, + } + cfg.Process() + handler = handlers.NewMtlsRoutePoliciesAuth(cfg, logger.Logger) + reqInfo = &handlers.RequestInfo{} + }) + + createPool := func(ep *route.Endpoint) *route.EndpointPool { + p := route.NewPool(&route.PoolOpts{ + Host: "backend.apps.mtls.internal", + }) + p.Put(ep) + return p + } + + Describe("Check", func() { + Context("when RoutePool is nil", func() { + It("denies with AuthError (defense in depth)", func() { + reqInfo.RoutePool = nil + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + }) + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("internal_error")) + Expect(authErr.Reason).To(Equal("route pool missing during authorization")) + }) + }) + + Context("when RoutePolicyScope is empty", func() { + It("returns nil (no enforcement active)", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: "", // No enforcement + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + }) + + It("skips enforcement when caller has identity", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: "", // No enforcement configured + RoutePolicies: []string{"cf:any"}, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "caller-space", + OrgGUID: "caller-org", + } + + // Even though caller has identity and route has policies, + // enforcement is skipped because RoutePolicyScope is empty + // (domain not configured for route policy enforcement) + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + }) + }) + + Context("when CallerIdentity is nil", func() { + It("returns AuthError (defense in depth)", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + RoutePolicies: []string{"cf:any"}, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = nil + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("route:no_caller_identity")) + Expect(authErr.Reason).To(Equal("no caller identity present")) + Expect(authErr.HTTPStatus).To(Equal(http.StatusForbidden)) + }) + }) + + Context("when no route policies are configured", func() { + It("denies with AuthError (default deny)", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + RoutePolicies: []string{}, // No sources = default deny + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("route:no_route_policies")) + Expect(authErr.Reason).To(Equal("route has no route policies configured")) + Expect(authErr.HTTPStatus).To(Equal(http.StatusForbidden)) + }) + + It("denies with AuthError when RoutePolicies is nil", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + RoutePolicies: nil, // Nil = default deny + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("route:no_route_policies")) + Expect(authErr.Reason).To(Equal("route has no route policies configured")) + Expect(authErr.HTTPStatus).To(Equal(http.StatusForbidden)) + }) + }) + + // ── Route policy: cf:any ─────────────────────────────────────── + + Context("with route policy cf:any", func() { + It("allows any authenticated caller", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{"cf:any"}, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "random-caller-app", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:any")) + }) + }) + + // ── Route policy: cf:app: ──────────────────────────────── + + Context("with route policy cf:app:", func() { + It("allows caller with matching app GUID", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{"cf:app:allowed-app-123"}, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "allowed-app-123", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:app:allowed-app-123")) + }) + + It("denies caller with different app GUID", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{"cf:app:allowed-app-123"}, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "other-app-456", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("route:route_policies")) + Expect(authErr.Reason).To(ContainSubstring("caller app other-app-456 not in route_policies")) + }) + }) + + // ── Route policy: cf:space: ────────────────────────────── + + Context("with route policy cf:space:", func() { + It("allows caller from matching space", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{"cf:space:allowed-space-abc"}, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "allowed-space-abc", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:space:allowed-space-abc")) + }) + + It("denies caller from different space", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{"cf:space:allowed-space-abc"}, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "other-space-xyz", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("route:route_policies")) + }) + }) + + // ── Route policy: cf:org: ──────────────────────────────── + + Context("with route policy cf:org:", func() { + It("allows caller from matching org", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{"cf:org:allowed-org-123"}, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + OrgGUID: "allowed-org-123", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:org:allowed-org-123")) + }) + + It("denies caller from different org", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{"cf:org:allowed-org-123"}, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + OrgGUID: "other-org-456", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("route:route_policies")) + }) + }) + + // ── Multiple route policies ───────────────────────────────────── + + Context("with multiple route policies", func() { + It("allows caller matching first rule", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{ + "cf:app:app-1", + "cf:app:app-2", + "cf:space:space-abc", + }, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "app-1", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:app:app-1")) + }) + + It("allows caller matching second rule", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{ + "cf:app:app-1", + "cf:app:app-2", + "cf:space:space-abc", + }, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "app-2", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:app:app-2")) + }) + + It("allows caller matching third rule", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{ + "cf:app:app-1", + "cf:app:app-2", + "cf:space:space-abc", + }, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "some-other-app", + SpaceGUID: "space-abc", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:space:space-abc")) + }) + + It("denies caller matching no rules", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{ + "cf:app:app-1", + "cf:app:app-2", + "cf:space:space-abc", + }, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "unrelated-app", + SpaceGUID: "unrelated-space", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("route:route_policies")) + }) + }) + + // ── Per-endpoint policies (shared routes with different backends) ── + + Context("when endpoints on same route have different route policies", func() { + It("uses selected endpoint's policies, not pool-level policies", func() { + // First endpoint allows only app-1 + endpoint1 := route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app-1", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{"cf:app:allowed-app-1"}, + }) + + // Second endpoint allows only app-2 + endpoint2 := route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app-2", + Host: "192.168.1.2", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{"cf:app:allowed-app-2"}, + }) + + // Create pool with both endpoints (pool-level policies will be from last endpoint) + pool = route.NewPool(&route.PoolOpts{ + Host: "shared.apps.mtls.internal", + }) + pool.Put(endpoint1) + pool.Put(endpoint2) + + // Pool-level policies are from endpoint2 (last registered) + Expect(pool.RoutePolicies()).To(Equal([]string{"cf:app:allowed-app-2"})) + + // Caller is allowed-app-1 + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "allowed-app-1", + } + + // When request is routed to endpoint1, it should succeed + // (uses endpoint1's policies, not pool-level policies) + err := handler.Check(endpoint1, reqInfo) + Expect(err).To(BeNil(), "should allow when endpoint's policy matches caller") + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:app:allowed-app-1")) + + // When request is routed to endpoint2, it should fail + // (endpoint2 only allows app-2, caller is app-1) + reqInfo.AuthResult = nil // Reset for next check + err = handler.Check(endpoint2, reqInfo) + Expect(err).NotTo(BeNil(), "should deny when endpoint's policy doesn't match caller") + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("route:route_policies")) + }) + }) + + // ── Edge cases ──────────────────────────────────────────────── + + Context("edge cases", func() { + It("handles whitespace in route policies", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{" cf:any "}, // Whitespace + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:any")) + }) + + It("skips malformed rules and evaluates valid ones", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + RoutePolicies: []string{ + "invalid-rule", + "cf:app:allowed-app", + }, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "allowed-app", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:app:allowed-app")) + }) + }) + }) + + Describe("NewMtlsRoutePoliciesAuth", func() { + Context("when no mTLS domains are configured", func() { + It("returns NoopPostSelectionHandler", func() { + logger := test_util.NewTestLogger("test") + emptyCfg, _ := config.DefaultConfig() + Expect(emptyCfg.Domains).To(BeEmpty()) + + handler := handlers.NewMtlsRoutePoliciesAuth(emptyCfg, logger.Logger) + Expect(handler).To(BeIdenticalTo(handlers.NoopPostSelectionHandler)) + }) + }) + + Context("when mTLS domains are configured", func() { + It("returns a real handler", func() { + logger := test_util.NewTestLogger("test") + cfg, _ := config.DefaultConfig() + certChain := test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.mtls.internal", + CACerts: string(certChain.CACertPEM), + }, + } + cfg.Process() + + handler := handlers.NewMtlsRoutePoliciesAuth(cfg, logger.Logger) + Expect(handler).NotTo(BeIdenticalTo(handlers.NoopPostSelectionHandler)) + }) + }) + }) +}) diff --git a/src/code.cloudfoundry.org/gorouter/handlers/mtls_scope_auth.go b/src/code.cloudfoundry.org/gorouter/handlers/mtls_scope_auth.go new file mode 100644 index 000000000..17d05c109 --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/mtls_scope_auth.go @@ -0,0 +1,107 @@ +package handlers + +import ( + "fmt" + "log/slog" + + "code.cloudfoundry.org/gorouter/config" + "code.cloudfoundry.org/gorouter/route" +) + +// MtlsScopeAuth performs post-selection domain-level scope authorization. +// It checks whether the caller's org/space identity matches the SELECTED +// endpoint's org/space tags, implementing the RFC's post-selection enforcement +// model. +// +// This handler runs AFTER endpoint selection (load balancing) and enforces +// strict scope boundaries. When a route is shared across spaces with scope=space, +// intermittent 403 errors are expected as the RFC acknowledges this as the +// tradeoff for strict per-endpoint authorization. +type MtlsScopeAuth struct { + config *config.Config + logger *slog.Logger +} + +// NewMtlsScopeAuth creates a new post-selection scope authorization handler. +// Returns NoopPostSelectionHandler when no mTLS domains are configured. +func NewMtlsScopeAuth(cfg *config.Config, logger *slog.Logger) PostSelectionHandler { + if len(cfg.Domains) == 0 { + return NoopPostSelectionHandler + } + return &MtlsScopeAuth{ + config: cfg, + logger: logger, + } +} + +// Check performs post-selection scope authorization against the selected endpoint. +// Returns nil if authorized, or an AuthError if the caller's org/space +// does not match the selected endpoint's org/space tags. +func (h *MtlsScopeAuth) Check(endpoint *route.Endpoint, reqInfo *RequestInfo) error { + // Get route policy scope from pool + if reqInfo.RoutePool == nil { + // This should not happen in normal operation, but if it does, + // we must deny the request to avoid authorization bypass + return NewAuthError("internal_error", "route pool missing during authorization") + } + + routePolicyScope := reqInfo.RoutePool.RoutePolicyScope() + if routePolicyScope == "" { + return nil // No scope enforcement configured + } + + // Scope enforcement requires caller identity + if reqInfo.CallerIdentity == nil { + // Defense in depth: identity should have been checked in pre-auth, + // but explicitly deny here to avoid silent authorization bypass + return NewAuthError( + "domain:no_caller_identity", + "no caller identity present", + ) + } + + identity := reqInfo.CallerIdentity + + // Perform post-selection scope check against the SELECTED endpoint's tags + switch routePolicyScope { + case route.RoutePolicyScopeOrg: + endpointOrg := endpoint.Tags["organization_id"] + if endpointOrg != identity.OrgGUID { + return NewAuthError( + "domain:scope=org:post-selection", + fmt.Sprintf("caller org %s does not match selected backend org %s", + identity.OrgGUID, endpointOrg), + ) + } + + case route.RoutePolicyScopeSpace: + endpointSpace := endpoint.Tags["space_id"] + if endpointSpace != identity.SpaceGUID { + return NewAuthError( + "domain:scope=space:post-selection", + fmt.Sprintf("caller space %s does not match selected backend space %s", + identity.SpaceGUID, endpointSpace), + ) + } + + case route.RoutePolicyScopeAny: + // Any authenticated caller passes scope check + // Fall through to populate AuthResult + + default: + // Unknown scope - deny to be safe + return NewAuthError( + "domain:scope=unknown:post-selection", + fmt.Sprintf("unknown route policy scope %q", routePolicyScope), + ) + } + + // Scope check passed - populate AuthResult for access logs + if reqInfo.AuthResult == nil { + reqInfo.AuthResult = &AuthResult{} + } + reqInfo.AuthResult.Outcome = "allowed" + reqInfo.AuthResult.Rule = fmt.Sprintf("domain:scope=%s", routePolicyScope) + + return nil +} diff --git a/src/code.cloudfoundry.org/gorouter/handlers/mtls_scope_auth_test.go b/src/code.cloudfoundry.org/gorouter/handlers/mtls_scope_auth_test.go new file mode 100644 index 000000000..5b9c148bb --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/mtls_scope_auth_test.go @@ -0,0 +1,452 @@ +package handlers_test + +import ( + "net/http" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "code.cloudfoundry.org/gorouter/config" + "code.cloudfoundry.org/gorouter/handlers" + "code.cloudfoundry.org/gorouter/route" + "code.cloudfoundry.org/gorouter/test_util" +) + +var _ = Describe("MtlsScopeAuth", func() { + var ( + handler handlers.PostSelectionHandler + endpoint *route.Endpoint + reqInfo *handlers.RequestInfo + pool *route.EndpointPool + cfg *config.Config + ) + + BeforeEach(func() { + logger := test_util.NewTestLogger("mtls-scope-auth") + cfg, _ = config.DefaultConfig() + // Configure a domain so the handler is active + certChain := test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.mtls.internal", + CACerts: string(certChain.CACertPEM), + }, + } + cfg.Process() + handler = handlers.NewMtlsScopeAuth(cfg, logger.Logger) + reqInfo = &handlers.RequestInfo{} + }) + + createPool := func(ep *route.Endpoint) *route.EndpointPool { + p := route.NewPool(&route.PoolOpts{ + Host: "backend.apps.mtls.internal", + }) + p.Put(ep) + return p + } + + Describe("Check", func() { + Context("when RoutePool is nil", func() { + It("denies with AuthError (defense in depth)", func() { + reqInfo.RoutePool = nil + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + }) + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("internal_error")) + Expect(authErr.Reason).To(Equal("route pool missing during authorization")) + }) + }) + + Context("when RoutePolicyScope is empty", func() { + It("returns nil (no enforcement active)", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: "", // No enforcement + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + }) + }) + + Context("when CallerIdentity is nil", func() { + It("returns AuthError (defense in depth)", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = nil + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("domain:no_caller_identity")) + Expect(authErr.Reason).To(Equal("no caller identity present")) + Expect(authErr.HTTPStatus).To(Equal(http.StatusForbidden)) + }) + }) + + // ── Scope: any ──────────────────────────────────────────────── + + Context("with scope=any", func() { + It("allows any authenticated caller", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeAny, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "any-caller-app", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult).NotTo(BeNil()) + Expect(reqInfo.AuthResult.Outcome).To(Equal("allowed")) + Expect(reqInfo.AuthResult.Rule).To(Equal("domain:scope=any")) + }) + }) + + // ── Scope: org ──────────────────────────────────────────────── + + Context("with scope=org", func() { + It("allows caller from same org", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{"organization_id": "org-123"}, + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + OrgGUID: "org-123", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + }) + + It("denies caller from different org with AuthError", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{"organization_id": "org-123"}, + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + OrgGUID: "org-456", // Different org + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue(), "error should be AuthError") + Expect(authErr.Rule).To(Equal("domain:scope=org:post-selection")) + Expect(authErr.Reason).To(ContainSubstring("caller org org-456 does not match selected backend org org-123")) + Expect(authErr.HTTPStatus).To(Equal(http.StatusForbidden)) + }) + + It("denies caller when endpoint has no organization_id tag", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{}, // No org tag + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + OrgGUID: "org-123", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("domain:scope=org:post-selection")) + Expect(authErr.Reason).To(ContainSubstring("caller org org-123 does not match selected backend org ")) + }) + + It("denies caller when caller has no org", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{"organization_id": "org-123"}, + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + OrgGUID: "", // No org + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("domain:scope=org:post-selection")) + }) + }) + + // ── Scope: space ────────────────────────────────────────────── + + Context("with scope=space", func() { + It("allows caller from same space", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{"space_id": "space-abc"}, + RoutePolicyScope: route.RoutePolicyScopeSpace, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "space-abc", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + }) + + It("denies caller from different space with AuthError", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{"space_id": "space-abc"}, + RoutePolicyScope: route.RoutePolicyScopeSpace, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "space-xyz", // Different space + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("domain:scope=space:post-selection")) + Expect(authErr.Reason).To(ContainSubstring("caller space space-xyz does not match selected backend space space-abc")) + Expect(authErr.HTTPStatus).To(Equal(http.StatusForbidden)) + }) + + It("denies caller when endpoint has no space_id tag", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{}, // No space tag + RoutePolicyScope: route.RoutePolicyScopeSpace, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "space-abc", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("domain:scope=space:post-selection")) + }) + + It("denies caller when caller has no space", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{"space_id": "space-abc"}, + RoutePolicyScope: route.RoutePolicyScopeSpace, + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "", // No space + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("domain:scope=space:post-selection")) + }) + }) + + // ── Scope: unknown ─────────────────────────────────────────── + + Context("with unknown scope", func() { + It("denies request with AuthError", func() { + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + RoutePolicyScope: "unknown-scope-value", + }) + pool = createPool(endpoint) + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + } + + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("domain:scope=unknown:post-selection")) + Expect(authErr.Reason).To(ContainSubstring("unknown route policy scope")) + Expect(authErr.HTTPStatus).To(Equal(http.StatusForbidden)) + }) + }) + + // ── Shared route scenario: intermittent 403s ───────────────── + + Context("shared route with scope=space (intermittent 403s)", func() { + It("allows request when selected endpoint matches caller's space", func() { + // Endpoint from space-abc + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app-1", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{"space_id": "space-abc"}, + RoutePolicyScope: route.RoutePolicyScopeSpace, + }) + + // Pool contains endpoints from multiple spaces (shared route) + pool = route.NewPool(&route.PoolOpts{ + Host: "shared.apps.mtls.internal", + }) + pool.Put(endpoint) + + // Another endpoint from space-xyz + endpoint2 := route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app-2", + Host: "192.168.1.2", + Port: 8080, + Tags: map[string]string{"space_id": "space-xyz"}, + RoutePolicyScope: route.RoutePolicyScopeSpace, + }) + pool.Put(endpoint2) + + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "space-abc", + } + + // Check against endpoint from space-abc (matches caller) + err := handler.Check(endpoint, reqInfo) + Expect(err).To(BeNil()) + }) + + It("denies request when selected endpoint is from different space (intermittent 403)", func() { + // Endpoint from space-xyz (will be selected) + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app-2", + Host: "192.168.1.2", + Port: 8080, + Tags: map[string]string{"space_id": "space-xyz"}, + RoutePolicyScope: route.RoutePolicyScopeSpace, + }) + + // Pool contains endpoints from multiple spaces (shared route) + pool = route.NewPool(&route.PoolOpts{ + Host: "shared.apps.mtls.internal", + }) + + // Endpoint from space-abc + endpoint1 := route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app-1", + Host: "192.168.1.1", + Port: 8080, + Tags: map[string]string{"space_id": "space-abc"}, + RoutePolicyScope: route.RoutePolicyScopeSpace, + }) + pool.Put(endpoint1) + pool.Put(endpoint) + + reqInfo.RoutePool = pool + reqInfo.CallerIdentity = &handlers.CallerIdentity{ + AppGUID: "caller-app", + SpaceGUID: "space-abc", // Caller from space-abc + } + + // Check against endpoint from space-xyz (selected, doesn't match) + err := handler.Check(endpoint, reqInfo) + Expect(err).NotTo(BeNil()) + + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("domain:scope=space:post-selection")) + Expect(authErr.Reason).To(ContainSubstring("caller space space-abc does not match selected backend space space-xyz")) + }) + }) + }) + + Describe("NewMtlsScopeAuth", func() { + Context("when no mTLS domains are configured", func() { + It("returns NoopPostSelectionHandler", func() { + logger := test_util.NewTestLogger("test") + emptyCfg, _ := config.DefaultConfig() + Expect(emptyCfg.Domains).To(BeEmpty()) + + handler := handlers.NewMtlsScopeAuth(emptyCfg, logger.Logger) + Expect(handler).To(BeIdenticalTo(handlers.NoopPostSelectionHandler)) + }) + }) + + Context("when mTLS domains are configured", func() { + It("returns a real handler", func() { + logger := test_util.NewTestLogger("test") + // cfg is already configured with domains in BeforeEach + handler := handlers.NewMtlsScopeAuth(cfg, logger.Logger) + Expect(handler).NotTo(BeIdenticalTo(handlers.NoopPostSelectionHandler)) + }) + }) + }) +}) diff --git a/src/code.cloudfoundry.org/gorouter/handlers/mtls_sni_check.go b/src/code.cloudfoundry.org/gorouter/handlers/mtls_sni_check.go new file mode 100644 index 000000000..d47696235 --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/mtls_sni_check.go @@ -0,0 +1,98 @@ +package handlers + +import ( + "log/slog" + "net/http" + "strings" + + "code.cloudfoundry.org/gorouter/config" + "github.com/urfave/negroni/v3" +) + +// mtlsSniCheck validates that the TLS SNI and Host header are consistent with +// the configured mTLS domains. It returns 421 Misdirected Request when a +// mismatch is detected. +// +// This handler runs BEFORE ClientCert/CfIdentity so that 421 responses skip +// certificate processing entirely (optimization from PR #535 thread 11). +// +// It does NOT perform identity or authorization checks — those happen in +// MtlsPreAuth which runs after CfIdentity has extracted the caller identity. +type mtlsSniCheck struct { + config *config.Config + logger *slog.Logger +} + +// NewMtlsSniCheck creates a new SNI/Host mismatch check handler. +// Returns NoopHandler when no mTLS domains are configured. +func NewMtlsSniCheck(cfg *config.Config, logger *slog.Logger) negroni.Handler { + if len(cfg.Domains) == 0 { + return NoopHandler + } + return &mtlsSniCheck{ + config: cfg, + logger: logger, + } +} + +func (h *mtlsSniCheck) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + reqInfo, err := ContextRequestInfo(r) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + hostDomain := hostWithoutPort(r.Host) + connState := GetTLSConnectionState(r) + reqInfo.TlsSNI = connState.SNI + + isMtlsDomain := h.config.IsMtlsDomain(hostDomain) + + // ── Layer 0: Non-mTLS domain handling ────────────────────────────────────── + if !isMtlsDomain { + // If the Host is NOT an mTLS domain but the client connected with client + // cert enforcement (for a different mTLS domain), verify consistency. + // This prevents SNI-to-Host confusion attacks. + if connState.ClientCertRequired && !domainMatches(hostDomain, connState.MtlsDomain) { + w.WriteHeader(http.StatusMisdirectedRequest) // 421 + return + } + next(w, r) + return + } + + // ── Layer 0b: mTLS domain - verify certificate was required ──────────────── + // For mTLS domains we verify that the TLS handshake actually enforced client + // certificate validation for *this* domain. Without this check an attacker + // could connect with SNI for a non-mTLS domain and then send a Host header + // pointing at an mTLS domain — bypassing certificate validation entirely. + if !connState.ClientCertRequired || !domainMatches(hostDomain, connState.MtlsDomain) { + w.WriteHeader(http.StatusMisdirectedRequest) // 421 + return + } + + // SNI/Host consistent with mTLS domain — continue to certificate processing + next(w, r) +} + +// domainMatches checks if a hostname matches a domain pattern (supports wildcard domains). +// Wildcard patterns (*.domain) only match a single DNS label, not multiple levels. +// Matching is case-insensitive per RFC 1035 (DNS hostnames). +func domainMatches(hostname, domainPattern string) bool { + // Normalize to lowercase for case-insensitive matching (RFC 1035) + hostname = strings.ToLower(hostname) + domainPattern = strings.ToLower(domainPattern) + + if hostname == domainPattern { + return true + } + if strings.HasPrefix(domainPattern, "*.") { + suffix := domainPattern[1:] // e.g. ".apps.identity" + if !strings.HasSuffix(hostname, suffix) { + return false + } + prefix := strings.TrimSuffix(hostname, suffix) + return !strings.Contains(prefix, ".") + } + return false +} diff --git a/src/code.cloudfoundry.org/gorouter/handlers/mtls_sni_check_test.go b/src/code.cloudfoundry.org/gorouter/handlers/mtls_sni_check_test.go new file mode 100644 index 000000000..7350c8bca --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/mtls_sni_check_test.go @@ -0,0 +1,359 @@ +package handlers_test + +import ( + "context" + "net/http" + "net/http/httptest" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/urfave/negroni/v3" + + "code.cloudfoundry.org/gorouter/config" + "code.cloudfoundry.org/gorouter/handlers" + "code.cloudfoundry.org/gorouter/test_util" +) + +var _ = Describe("MtlsSniCheck", func() { + var ( + handler negroni.Handler + cfg *config.Config + req *http.Request + resp *httptest.ResponseRecorder + reqInfo *handlers.RequestInfo + nextCalled bool + ) + + BeforeEach(func() { + logger := test_util.NewTestLogger("mtls-sni-check") + cfg, _ = config.DefaultConfig() + + certChain := test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.identity", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "exact.mtls.domain", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + } + err := cfg.Process() + Expect(err).ToNot(HaveOccurred()) + + handler = handlers.NewMtlsSniCheck(cfg, logger.Logger) + + req = test_util.NewRequest("GET", "example.com", "/", nil) + resp = httptest.NewRecorder() + reqInfo = &handlers.RequestInfo{} + + ctx := context.WithValue(req.Context(), handlers.RequestInfoCtxKey, reqInfo) + req = req.WithContext(ctx) + + nextCalled = false + }) + + nextHandler := func() http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + nextCalled = true + w.WriteHeader(http.StatusOK) + }) + } + + setTLSConnState := func(sni, mtlsDomain string, clientCertRequired bool) { + connState := &handlers.TLSConnState{ + SNI: sni, + MtlsDomain: mtlsDomain, + ClientCertRequired: clientCertRequired, + } + ctx := handlers.SetTLSConnState(req.Context(), connState) + req = req.WithContext(ctx) + } + + Describe("ServeHTTP", func() { + Context("Non-mTLS domain", func() { + It("passes through for non-mTLS domains without client cert", func() { + req.Host = "regular.example.com" + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeTrue()) + Expect(resp.Code).To(Equal(http.StatusOK)) + }) + + It("passes through for non-mTLS domains with port", func() { + req.Host = "regular.example.com:8080" + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeTrue()) + Expect(resp.Code).To(Equal(http.StatusOK)) + }) + + It("returns 421 when ClientCertRequired but MtlsDomain does not match non-mTLS host", func() { + req.Host = "regular.example.com" + setTLSConnState("backend.apps.identity", "*.apps.identity", true) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeFalse()) + Expect(resp.Code).To(Equal(http.StatusMisdirectedRequest)) + }) + }) + + Context("mTLS domain - SNI/Host mismatch check", func() { + BeforeEach(func() { + req.Host = "backend.apps.identity" + }) + + It("returns 421 when ClientCertRequired is false", func() { + setTLSConnState("backend.apps.identity", "", false) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeFalse()) + Expect(resp.Code).To(Equal(http.StatusMisdirectedRequest)) + Expect(reqInfo.TlsSNI).To(Equal("backend.apps.identity")) + }) + + It("returns 421 when MtlsDomain does not match Host", func() { + setTLSConnState("backend.apps.identity", "other.domain", true) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeFalse()) + Expect(resp.Code).To(Equal(http.StatusMisdirectedRequest)) + }) + + It("returns 421 when MtlsDomain is wildcard but Host doesn't match", func() { + req.Host = "attacker.evil.com" + setTLSConnState("good.apps.identity", "*.apps.identity", true) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeFalse()) + Expect(resp.Code).To(Equal(http.StatusMisdirectedRequest)) + }) + + It("passes when Host matches wildcard MtlsDomain", func() { + setTLSConnState("backend.apps.identity", "*.apps.identity", true) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeTrue()) + Expect(resp.Code).To(Equal(http.StatusOK)) + }) + + It("passes when Host matches exact MtlsDomain", func() { + req.Host = "exact.mtls.domain" + setTLSConnState("exact.mtls.domain", "exact.mtls.domain", true) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeTrue()) + Expect(resp.Code).To(Equal(http.StatusOK)) + }) + + It("sets TlsSNI on reqInfo", func() { + setTLSConnState("backend.apps.identity", "*.apps.identity", true) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(reqInfo.TlsSNI).To(Equal("backend.apps.identity")) + }) + }) + + Context("when RequestInfo is missing from context", func() { + It("returns 500", func() { + req = test_util.NewRequest("GET", "example.com", "/", nil) + + handler.ServeHTTP(resp, req, nextHandler()) + + Expect(nextCalled).To(BeFalse()) + Expect(resp.Code).To(Equal(http.StatusInternalServerError)) + }) + }) + }) +}) + +var _ = Describe("domainMatches", func() { + // domainMatches is tested via the MtlsSniCheck handler since it's unexported + var ( + handler negroni.Handler + cfg *config.Config + ) + + BeforeEach(func() { + logger := test_util.NewTestLogger("domain-matches") + cfg, _ = config.DefaultConfig() + certChain := test_util.CreateSignedCertWithRootCA(test_util.CertNames{SANs: test_util.SubjectAltNames{DNS: "test.com"}}) + cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.identity", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "exact.domain.com", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "wrong.domain.com", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "*.different.com", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "backend.appsxidentity", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "*.sub.apps.identity", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + { + Domain: "apps.identity", + XFCCFormat: "envoy", + CACerts: string(certChain.CACertPEM), + }, + } + err := cfg.Process() + Expect(err).ToNot(HaveOccurred()) + handler = handlers.NewMtlsSniCheck(cfg, logger.Logger) + }) + + testDomainMatch := func(host, sni, mtlsDomain string, clientCertRequired bool, expectedToPass bool) { + req := test_util.NewRequest("GET", host, "/", nil) + resp := httptest.NewRecorder() + reqInfo := &handlers.RequestInfo{} + + ctx := context.WithValue(req.Context(), handlers.RequestInfoCtxKey, reqInfo) + connState := &handlers.TLSConnState{ + SNI: sni, + MtlsDomain: mtlsDomain, + ClientCertRequired: clientCertRequired, + } + ctx = handlers.SetTLSConnState(ctx, connState) + req = req.WithContext(ctx) + + nextCalled := false + next := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + nextCalled = true + w.WriteHeader(http.StatusOK) + }) + + handler.ServeHTTP(resp, req, next) + + if expectedToPass { + Expect(nextCalled).To(BeTrue(), "Expected next handler to be called for %s matching %s", host, mtlsDomain) + Expect(resp.Code).To(Equal(http.StatusOK)) + } else { + Expect(nextCalled).To(BeFalse(), "Expected 421 for %s not matching %s", host, mtlsDomain) + Expect(resp.Code).To(Equal(http.StatusMisdirectedRequest)) + } + } + + Describe("exact match", func() { + It("matches when hostname equals domain pattern", func() { + testDomainMatch("exact.domain.com", "exact.domain.com", "exact.domain.com", true, true) + }) + + It("does not match when hostname differs from domain pattern", func() { + testDomainMatch("wrong.domain.com", "wrong.domain.com", "exact.domain.com", true, false) + }) + }) + + Describe("wildcard match", func() { + It("matches single-label subdomain", func() { + testDomainMatch("backend.apps.identity", "backend.apps.identity", "*.apps.identity", true, true) + }) + + It("matches different single-label subdomain", func() { + testDomainMatch("frontend.apps.identity", "frontend.apps.identity", "*.apps.identity", true, true) + }) + + It("does NOT match multi-label subdomain", func() { + testDomainMatch("deep.sub.apps.identity", "deep.sub.apps.identity", "*.apps.identity", true, false) + }) + + It("does not match different domain suffix", func() { + testDomainMatch("backend.different.com", "backend.different.com", "*.apps.identity", true, false) + }) + + It("does not match when suffix is similar but not exact", func() { + testDomainMatch("backend.appsxidentity", "backend.appsxidentity", "*.apps.identity", true, false) + }) + + It("does not match bare domain without subdomain", func() { + testDomainMatch("apps.identity", "apps.identity", "*.apps.identity", true, false) + }) + }) + + Describe("with port in hostname", func() { + It("matches exact domain with port", func() { + testDomainMatch("exact.domain.com:8080", "exact.domain.com", "exact.domain.com", true, true) + }) + + It("matches wildcard domain with port", func() { + testDomainMatch("backend.apps.identity:443", "backend.apps.identity", "*.apps.identity", true, true) + }) + }) + + Describe("case-insensitive matching (Thread 15: hostname not lowercased in domainMatches)", func() { + // Per RFC 1035, DNS hostnames are case-insensitive, so: + // - "BACKEND.apps.identity" should match "*.apps.identity" + // - "backend.APPS.IDENTITY" should match "*.apps.identity" + + It("matches when hostname has uppercase subdomain", func() { + testDomainMatch("BACKEND.apps.identity", "BACKEND.apps.identity", "*.apps.identity", true, true) + }) + + It("matches when hostname has uppercase suffix", func() { + testDomainMatch("backend.APPS.IDENTITY", "backend.APPS.IDENTITY", "*.apps.identity", true, true) + }) + + It("matches when hostname is fully uppercase", func() { + testDomainMatch("BACKEND.APPS.IDENTITY", "BACKEND.APPS.IDENTITY", "*.apps.identity", true, true) + }) + + It("matches exact domain with different casing", func() { + testDomainMatch("EXACT.DOMAIN.COM", "EXACT.DOMAIN.COM", "exact.domain.com", true, true) + }) + + It("matches when MtlsDomain pattern has mixed case (from config)", func() { + testDomainMatch("backend.apps.identity", "backend.apps.identity", "*.Apps.Identity", true, true) + }) + }) + + Describe("NewMtlsSniCheck", func() { + Context("when no mTLS domains are configured", func() { + It("returns NoopHandler", func() { + logger := test_util.NewTestLogger("test") + emptyCfg, _ := config.DefaultConfig() + Expect(emptyCfg.Domains).To(BeEmpty()) + + handler := handlers.NewMtlsSniCheck(emptyCfg, logger.Logger) + Expect(handler).To(BeIdenticalTo(handlers.NoopHandler)) + }) + }) + + Context("when mTLS domains are configured", func() { + It("returns a real handler", func() { + logger := test_util.NewTestLogger("test") + // cfg is already configured with domains in BeforeEach + handler := handlers.NewMtlsSniCheck(cfg, logger.Logger) + Expect(handler).NotTo(BeIdenticalTo(handlers.NoopHandler)) + }) + }) + }) +}) diff --git a/src/code.cloudfoundry.org/gorouter/handlers/noop.go b/src/code.cloudfoundry.org/gorouter/handlers/noop.go new file mode 100644 index 000000000..7c4bc59ad --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/noop.go @@ -0,0 +1,30 @@ +package handlers + +import ( + "net/http" + + "code.cloudfoundry.org/gorouter/route" + "github.com/urfave/negroni/v3" +) + +// noopNegroniHandler is a negroni handler that does nothing but call the next handler. +type noopNegroniHandler struct{} + +func (h *noopNegroniHandler) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + next(w, r) +} + +// NoopHandler is a negroni handler that does nothing but call the next handler. +// Use this when a handler should be conditionally disabled based on configuration. +var NoopHandler negroni.Handler = &noopNegroniHandler{} + +// noopPostSelectionHandler is a PostSelectionHandler that always allows the request. +type noopPostSelectionHandler struct{} + +func (h *noopPostSelectionHandler) Check(endpoint *route.Endpoint, reqInfo *RequestInfo) error { + return nil +} + +// NoopPostSelectionHandler is a PostSelectionHandler that does nothing. +// Use this when a post-selection handler should be conditionally disabled. +var NoopPostSelectionHandler PostSelectionHandler = &noopPostSelectionHandler{} diff --git a/src/code.cloudfoundry.org/gorouter/handlers/post_selection_pipeline.go b/src/code.cloudfoundry.org/gorouter/handlers/post_selection_pipeline.go new file mode 100644 index 000000000..afb1fc20e --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/post_selection_pipeline.go @@ -0,0 +1,55 @@ +package handlers + +import ( + "log/slog" + + "code.cloudfoundry.org/gorouter/route" +) + +// PostSelectionHandler represents a single authorization check that runs after +// endpoint selection. Each handler inspects the selected endpoint and request +// context to make an authorization decision. +// +// Handlers are composable and run in sequence. The first handler to return an +// error stops the pipeline and causes the request to be rejected. +// +//go:generate counterfeiter -o fakes/fake_post_selection_handler.go . PostSelectionHandler +type PostSelectionHandler interface { + // Check performs an authorization check against the selected endpoint. + // Returns nil if authorized, or an AuthError if denied. + Check(endpoint *route.Endpoint, reqInfo *RequestInfo) error +} + +// PostSelectionPipeline runs a sequence of post-selection authorization handlers. +// This enables composable, layered authorization checks after the load balancer +// has selected a specific backend endpoint. +type PostSelectionPipeline struct { + handlers []PostSelectionHandler + logger *slog.Logger +} + +// NewPostSelectionPipeline creates a new authorization pipeline with the given handlers. +// Handlers are executed in the order provided. +func NewPostSelectionPipeline(logger *slog.Logger, handlers ...PostSelectionHandler) *PostSelectionPipeline { + return &PostSelectionPipeline{ + handlers: handlers, + logger: logger, + } +} + +// Run executes all handlers in sequence. Returns nil if all handlers pass, +// or the first error encountered. +func (p *PostSelectionPipeline) Run(endpoint *route.Endpoint, reqInfo *RequestInfo) error { + if p == nil || len(p.handlers) == 0 { + return nil // No handlers configured, allow request + } + + for _, handler := range p.handlers { + if err := handler.Check(endpoint, reqInfo); err != nil { + // First failure stops the pipeline + return err + } + } + + return nil // All handlers passed +} diff --git a/src/code.cloudfoundry.org/gorouter/handlers/post_selection_pipeline_test.go b/src/code.cloudfoundry.org/gorouter/handlers/post_selection_pipeline_test.go new file mode 100644 index 000000000..1673fadc2 --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/handlers/post_selection_pipeline_test.go @@ -0,0 +1,281 @@ +package handlers_test + +import ( + "errors" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "code.cloudfoundry.org/gorouter/handlers" + "code.cloudfoundry.org/gorouter/handlers/fakes" + "code.cloudfoundry.org/gorouter/route" + "code.cloudfoundry.org/gorouter/test_util" +) + +var _ = Describe("PostSelectionPipeline", func() { + var ( + pipeline *handlers.PostSelectionPipeline + handler1 *fakes.FakePostSelectionHandler + handler2 *fakes.FakePostSelectionHandler + handler3 *fakes.FakePostSelectionHandler + endpoint *route.Endpoint + reqInfo *handlers.RequestInfo + authError *handlers.AuthError + genericErr error + ) + + BeforeEach(func() { + handler1 = &fakes.FakePostSelectionHandler{} + handler2 = &fakes.FakePostSelectionHandler{} + handler3 = &fakes.FakePostSelectionHandler{} + + endpoint = route.NewEndpoint(&route.EndpointOpts{ + AppId: "backend-app", + Host: "192.168.1.1", + Port: 8080, + }) + + reqInfo = &handlers.RequestInfo{} + + authError = handlers.NewAuthError("test:rule", "test reason") + genericErr = errors.New("generic error") + }) + + Describe("Run", func() { + Context("with empty pipeline", func() { + It("returns nil", func() { + logger := test_util.NewTestLogger("pipeline") + pipeline = handlers.NewPostSelectionPipeline(logger.Logger) + err := pipeline.Run(endpoint, reqInfo) + Expect(err).To(BeNil()) + }) + }) + + Context("with single handler", func() { + It("calls the handler and returns nil on success", func() { + logger := test_util.NewTestLogger("pipeline") + handler1.CheckReturns(nil) + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1) + + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(BeNil()) + Expect(handler1.CheckCallCount()).To(Equal(1)) + ep, ri := handler1.CheckArgsForCall(0) + Expect(ep).To(Equal(endpoint)) + Expect(ri).To(Equal(reqInfo)) + }) + + It("returns error when handler fails", func() { + logger := test_util.NewTestLogger("pipeline") + handler1.CheckReturns(authError) + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1) + + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(Equal(authError)) + Expect(handler1.CheckCallCount()).To(Equal(1)) + }) + }) + + Context("with multiple handlers", func() { + It("calls all handlers in order when all succeed", func() { + logger := test_util.NewTestLogger("pipeline") + handler1.CheckReturns(nil) + handler2.CheckReturns(nil) + handler3.CheckReturns(nil) + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1, handler2, handler3) + + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(BeNil()) + Expect(handler1.CheckCallCount()).To(Equal(1)) + Expect(handler2.CheckCallCount()).To(Equal(1)) + Expect(handler3.CheckCallCount()).To(Equal(1)) + + // Verify all received same endpoint and reqInfo + ep1, ri1 := handler1.CheckArgsForCall(0) + ep2, ri2 := handler2.CheckArgsForCall(0) + ep3, ri3 := handler3.CheckArgsForCall(0) + + Expect(ep1).To(Equal(endpoint)) + Expect(ep2).To(Equal(endpoint)) + Expect(ep3).To(Equal(endpoint)) + Expect(ri1).To(Equal(reqInfo)) + Expect(ri2).To(Equal(reqInfo)) + Expect(ri3).To(Equal(reqInfo)) + }) + + It("stops on first error and does not call remaining handlers", func() { + logger := test_util.NewTestLogger("pipeline") + handler1.CheckReturns(nil) + handler2.CheckReturns(authError) // Fails here + handler3.CheckReturns(nil) + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1, handler2, handler3) + + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(Equal(authError)) + Expect(handler1.CheckCallCount()).To(Equal(1)) + Expect(handler2.CheckCallCount()).To(Equal(1)) + Expect(handler3.CheckCallCount()).To(Equal(0)) // Should not be called + }) + + It("stops on first handler error", func() { + logger := test_util.NewTestLogger("pipeline") + handler1.CheckReturns(authError) // Fails immediately + handler2.CheckReturns(nil) + handler3.CheckReturns(nil) + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1, handler2, handler3) + + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(Equal(authError)) + Expect(handler1.CheckCallCount()).To(Equal(1)) + Expect(handler2.CheckCallCount()).To(Equal(0)) // Should not be called + Expect(handler3.CheckCallCount()).To(Equal(0)) // Should not be called + }) + + It("stops on third handler error", func() { + logger := test_util.NewTestLogger("pipeline") + handler1.CheckReturns(nil) + handler2.CheckReturns(nil) + handler3.CheckReturns(authError) // Fails at the end + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1, handler2, handler3) + + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(Equal(authError)) + Expect(handler1.CheckCallCount()).To(Equal(1)) + Expect(handler2.CheckCallCount()).To(Equal(1)) + Expect(handler3.CheckCallCount()).To(Equal(1)) + }) + }) + + Context("error type handling", func() { + It("returns AuthError as-is", func() { + logger := test_util.NewTestLogger("pipeline") + handler1.CheckReturns(authError) + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1) + + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(Equal(authError)) + authErr, ok := err.(*handlers.AuthError) + Expect(ok).To(BeTrue()) + Expect(authErr.Rule).To(Equal("test:rule")) + Expect(authErr.Reason).To(Equal("test reason")) + }) + + It("returns generic errors as-is", func() { + logger := test_util.NewTestLogger("pipeline") + handler1.CheckReturns(genericErr) + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1) + + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(Equal(genericErr)) + Expect(err.Error()).To(Equal("generic error")) + }) + }) + + Context("handler state isolation", func() { + It("does not interfere with reqInfo modifications by handlers", func() { + logger := test_util.NewTestLogger("pipeline") + // Handler 1 modifies reqInfo + handler1.CheckStub = func(ep *route.Endpoint, ri *handlers.RequestInfo) error { + if ri.AuthResult == nil { + ri.AuthResult = &handlers.AuthResult{} + } + ri.AuthResult.Rule = "first-rule" + return nil + } + + // Handler 2 should see the modification + handler2.CheckStub = func(ep *route.Endpoint, ri *handlers.RequestInfo) error { + Expect(ri.AuthResult.Rule).To(Equal("first-rule")) + ri.AuthResult.Rule = "second-rule" + return nil + } + + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1, handler2) + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("second-rule")) + }) + }) + + Context("real-world scenario", func() { + It("runs scope check then route policies check", func() { + logger := test_util.NewTestLogger("pipeline") + // Simulate scope check (passes) + handler1.CheckStub = func(ep *route.Endpoint, ri *handlers.RequestInfo) error { + // Scope check passed - no error + return nil + } + + // Simulate route policies check (passes and sets AuthResult.Rule) + handler2.CheckStub = func(ep *route.Endpoint, ri *handlers.RequestInfo) error { + // Route policies matched + if ri.AuthResult == nil { + ri.AuthResult = &handlers.AuthResult{} + } + ri.AuthResult.Rule = "route:cf:app:allowed-app" + return nil + } + + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1, handler2) + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(BeNil()) + Expect(reqInfo.AuthResult.Rule).To(Equal("route:cf:app:allowed-app")) + }) + + It("returns error from scope check before running route policies", func() { + logger := test_util.NewTestLogger("pipeline") + scopeErr := handlers.NewAuthError( + "domain:scope=org:post-selection", + "caller org mismatch", + ) + + // Simulate scope check (fails) + handler1.CheckReturns(scopeErr) + + // Simulate route policies check (should not be called) + handler2.CheckStub = func(ep *route.Endpoint, ri *handlers.RequestInfo) error { + Fail("route policies handler should not be called") + return nil + } + + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1, handler2) + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(Equal(scopeErr)) + Expect(handler1.CheckCallCount()).To(Equal(1)) + Expect(handler2.CheckCallCount()).To(Equal(0)) + }) + + It("returns error from route policies check when scope passes", func() { + logger := test_util.NewTestLogger("pipeline") + accessErr := handlers.NewAuthError( + "route:route_policies", + "caller not in route policies", + ) + + // Simulate scope check (passes) + handler1.CheckReturns(nil) + + // Simulate route policies check (fails) + handler2.CheckReturns(accessErr) + + pipeline = handlers.NewPostSelectionPipeline(logger.Logger, handler1, handler2) + err := pipeline.Run(endpoint, reqInfo) + + Expect(err).To(Equal(accessErr)) + Expect(handler1.CheckCallCount()).To(Equal(1)) + Expect(handler2.CheckCallCount()).To(Equal(1)) + }) + }) + }) +}) diff --git a/src/code.cloudfoundry.org/gorouter/handlers/requestinfo.go b/src/code.cloudfoundry.org/gorouter/handlers/requestinfo.go index 6d2a76819..a7779e627 100644 --- a/src/code.cloudfoundry.org/gorouter/handlers/requestinfo.go +++ b/src/code.cloudfoundry.org/gorouter/handlers/requestinfo.go @@ -23,6 +23,39 @@ type key string const RequestInfoCtxKey key = "RequestInfo" +// TLSConnStateKey is the context key type for TLSConnState. +// Exported so router.go can retrieve the pointer during the TLS handshake. +type TLSConnStateKey struct{} + +// TLSConnState captures per-connection TLS handshake state. +// It is stored in a connection-scoped context via http.Server.ConnContext +// (set by router.go) and retrieved per-request in authorization handlers. +type TLSConnState struct { + // SNI is the Server Name Indication value from the TLS ClientHello. + SNI string + // MtlsDomain is the matched mTLS domain name (empty if none matched). + MtlsDomain string + // ClientCertRequired is true when GoRouter required and validated a client + // certificate during the TLS handshake for this connection. + ClientCertRequired bool +} + +// SetTLSConnState stores the TLSConnState in a context (for use in ConnContext). +func SetTLSConnState(ctx context.Context, state *TLSConnState) context.Context { + return context.WithValue(ctx, TLSConnStateKey{}, state) +} + +// GetTLSConnectionState retrieves the TLSConnState from the request context. +// Returns a zero-value TLSConnState (not nil) if none was set (e.g. plain HTTP). +func GetTLSConnectionState(r *http.Request) TLSConnState { + if v := r.Context().Value(TLSConnStateKey{}); v != nil { + if state, ok := v.(*TLSConnState); ok && state != nil { + return *state + } + } + return TLSConnState{} +} + type TraceInfo struct { TraceID string SpanID string @@ -81,6 +114,17 @@ type RequestInfo struct { TraceInfo TraceInfo BackendReqHeaders http.Header + + // CallerIdentity contains the identity of the calling application extracted + // from the client certificate. Will be nil for requests without identity. + CallerIdentity *CallerIdentity + + // AuthResult captures the outcome of identity-aware routing authorization. + // Will be nil if no authorization was performed. + AuthResult *AuthResult + + // TlsSNI is the SNI value used during the TLS handshake (for RTR log on 421). + TlsSNI string } func (r *RequestInfo) ProvideTraceInfo() (TraceInfo, error) { diff --git a/src/code.cloudfoundry.org/gorouter/integration/common_integration_test.go b/src/code.cloudfoundry.org/gorouter/integration/common_integration_test.go index 41cf16cd5..af33cf741 100644 --- a/src/code.cloudfoundry.org/gorouter/integration/common_integration_test.go +++ b/src/code.cloudfoundry.org/gorouter/integration/common_integration_test.go @@ -1,12 +1,14 @@ package integration import ( + "context" "crypto/tls" "crypto/x509" "encoding/json" "fmt" "io" "math/rand" + "net" "net/http" "net/http/httptest" "os" @@ -191,6 +193,65 @@ func (s *testState) newGetRequest(url string) *http.Request { return req } +// newMtlsGetRequest creates a GET request for mTLS domains (*.apps.mtls.internal). +// It uses a custom dialer to connect to 127.0.0.1 while preserving the original +// hostname for TLS SNI, which is required for GoRouter's SNI/Host validation. +// This helper returns a specialized client that should be used instead of testState.client. +func (s *testState) newMtlsGetRequest(url string) (*http.Request, *http.Client) { + req, err := http.NewRequest("GET", url, nil) + Expect(err).NotTo(HaveOccurred()) + + // Parse the original hostname for SNI + originalHost := req.URL.Hostname() + port := s.cfg.SSLPort + + // Get the base transport to access current TLS config (including any client certs set by tests) + baseTransport := s.client.Transport.(*http.Transport) + + // Create custom transport with dialer that connects to 127.0.0.1 but uses original hostname for SNI + transport := &http.Transport{ + DialTLSContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + // Read certificates at dial time (not at closure creation time) so we get + // any certificates that tests set after calling newMtlsGetRequest() + currentCerts := baseTransport.TLSClientConfig.Certificates + + // Create TLS config for this connection + tlsConfig := &tls.Config{ + ServerName: originalHost, // SNI uses original hostname + RootCAs: baseTransport.TLSClientConfig.RootCAs, + Certificates: currentCerts, // Use current certificates from baseTransport + InsecureSkipVerify: true, // Skip cert verification since we connect to 127.0.0.1 + } + + // Create a plain dialer for the TCP connection + netDialer := &net.Dialer{} + rawConn, err := netDialer.DialContext(ctx, network, fmt.Sprintf("127.0.0.1:%d", port)) + if err != nil { + return nil, err + } + + // Wrap with TLS + tlsConn := tls.Client(rawConn, tlsConfig) + + // Perform handshake + if err := tlsConn.HandshakeContext(ctx); err != nil { + rawConn.Close() + return nil, err + } + + return tlsConn, nil + }, + } + + // Create a new client with the custom transport + client := &http.Client{ + Transport: transport, + Timeout: s.client.Timeout, + } + + return req, client +} + func (s *testState) register(backend *httptest.Server, routeURI string) { s.registerAsTLS(backend, routeURI, "") } @@ -247,6 +308,105 @@ func (s *testState) registerWithInternalRouteService(appBackend, routeServiceSer s.registerAndWait(rm) } +func (s *testState) registerWithAccessRules(backend *httptest.Server, routeURI string, accessRules map[string]interface{}) { + _, backendPort := hostnameAndPort(backend.Listener.Addr().String()) + + // Build route policy sources from map (using RFC-compliant format) + var accessRulesList []string + if apps, ok := accessRules["apps"].([]string); ok { + for _, app := range apps { + accessRulesList = append(accessRulesList, fmt.Sprintf("cf:app:%s", app)) + } + } + if spaces, ok := accessRules["spaces"].([]string); ok { + for _, space := range spaces { + accessRulesList = append(accessRulesList, fmt.Sprintf("cf:space:%s", space)) + } + } + if orgs, ok := accessRules["orgs"].([]string); ok { + for _, org := range orgs { + accessRulesList = append(accessRulesList, fmt.Sprintf("cf:org:%s", org)) + } + } + if any, ok := accessRules["any"].(bool); ok && any { + accessRulesList = append(accessRulesList, "cf:any") + } + + // Join route policy sources into comma-separated string + accessRulesStr := "" + if len(accessRulesList) > 0 { + accessRulesStr = accessRulesList[0] + for i := 1; i < len(accessRulesList); i++ { + accessRulesStr = fmt.Sprintf("%s,%s", accessRulesStr, accessRulesList[i]) + } + } + + rm := mbus.RegistryMessage{ + Host: "127.0.0.1", + Port: uint16(backendPort), + Uris: []route.Uri{route.Uri(routeURI)}, + StaleThresholdInSeconds: 10, + PrivateInstanceID: fmt.Sprintf("%x", rand.Int31()), + Options: mbus.RegistryMessageOpts{ + RoutePolicyScope: "any", // Default to any scope + RoutePolicySources: accessRulesStr, + }, + } + s.registerAndWait(rm) +} + +// registerWithScopeAndAccessRules registers a route with RFC-compliant access control. +// scope: "any", "org", or "space" +// accessRules: map with "apps", "spaces", "orgs", or "any" keys +// tags: endpoint tags like "organization_id" and "space_id" +func (s *testState) registerWithScopeAndAccessRules(backend *httptest.Server, routeURI string, scope string, accessRules map[string]interface{}, tags map[string]string) { + _, backendPort := hostnameAndPort(backend.Listener.Addr().String()) + + // Build route policy sources from map + var accessRulesList []string + if apps, ok := accessRules["apps"].([]string); ok { + for _, app := range apps { + accessRulesList = append(accessRulesList, fmt.Sprintf("cf:app:%s", app)) + } + } + if spaces, ok := accessRules["spaces"].([]string); ok { + for _, space := range spaces { + accessRulesList = append(accessRulesList, fmt.Sprintf("cf:space:%s", space)) + } + } + if orgs, ok := accessRules["orgs"].([]string); ok { + for _, org := range orgs { + accessRulesList = append(accessRulesList, fmt.Sprintf("cf:org:%s", org)) + } + } + if any, ok := accessRules["any"].(bool); ok && any { + accessRulesList = append(accessRulesList, "cf:any") + } + + // Join route policy sources into comma-separated string + accessRulesStr := "" + if len(accessRulesList) > 0 { + accessRulesStr = accessRulesList[0] + for i := 1; i < len(accessRulesList); i++ { + accessRulesStr = fmt.Sprintf("%s,%s", accessRulesStr, accessRulesList[i]) + } + } + + rm := mbus.RegistryMessage{ + Host: "127.0.0.1", + Port: uint16(backendPort), + Uris: []route.Uri{route.Uri(routeURI)}, + StaleThresholdInSeconds: 10, + PrivateInstanceID: fmt.Sprintf("%x", rand.Int31()), + Tags: tags, + Options: mbus.RegistryMessageOpts{ + RoutePolicyScope: scope, + RoutePolicySources: accessRulesStr, + }, + } + s.registerAndWait(rm) +} + func (s *testState) registerAndWait(rm mbus.RegistryMessage) { b, _ := json.Marshal(rm) s.mbusClient.Publish("router.register", b) @@ -308,7 +468,7 @@ func (s *testState) StartGorouterOrFail() { func (s *testState) StopAndCleanup() { // Stop router before NATS to prevent subscriber's ClosedCB from - // firing log.Fatal → os.Exit(1), which kills the test proc. + // firing log.Fatal → os.Exit(1), which kills the test proc if s.gorouterSession != nil && s.gorouterSession.ExitCode() == -1 { Eventually(s.gorouterSession.Terminate(), 5).Should(Exit(0)) } diff --git a/src/code.cloudfoundry.org/gorouter/integration/identity_aware_routing_test.go b/src/code.cloudfoundry.org/gorouter/integration/identity_aware_routing_test.go new file mode 100644 index 000000000..1511abc0d --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/integration/identity_aware_routing_test.go @@ -0,0 +1,910 @@ +package integration + +import ( + "crypto/tls" + "fmt" + "io" + "net/http" + "net/http/httptest" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "code.cloudfoundry.org/gorouter/config" + "code.cloudfoundry.org/gorouter/test_util" +) + +var _ = Describe("Identity-Aware Routing", func() { + var testState *testState + + BeforeEach(func() { + testState = NewTestState() + }) + + AfterEach(func() { + if testState != nil { + testState.StopAndCleanup() + } + }) + + Describe("mTLS domain configuration", func() { + var ( + mtlsDomainCA *test_util.CertChain + appInstanceCert *test_util.CertChain + backendApp *httptest.Server + backendReceivedReqs chan *http.Request + ) + + BeforeEach(func() { + // Create CA for mTLS domain (simulates Diego instance identity CA) + mtlsDomainCA = &test_util.CertChain{} + *mtlsDomainCA = test_util.CreateSignedCertWithRootCA(test_util.CertNames{CommonName: "Diego Instance Identity CA"}) + + // Setup backend app + backendReceivedReqs = make(chan *http.Request, 10) + backendApp = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + backendReceivedReqs <- r + w.WriteHeader(http.StatusOK) + w.Write([]byte("backend-response")) + })) + + // Configure GoRouter with mTLS domain + testState.cfg.EnableSSL = true + testState.cfg.ClientCertificateValidationString = "request" + }) + + AfterEach(func() { + if backendApp != nil { + backendApp.Close() + } + }) + + Context("when a request is made to an mTLS domain", func() { + var mtlsDomain string + + BeforeEach(func() { + mtlsDomain = "my-app.apps.mtls.internal" + + // Configure mTLS domain in GoRouter + testState.cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.mtls.internal", + CACerts: string(mtlsDomainCA.CACertPEM), + ForwardedClientCert: config.SANITIZE_SET, + }, + } + + testState.StartGorouterOrFail() + }) + + It("requires a client certificate", func() { + // Register route on mTLS domain + testState.register(backendApp, mtlsDomain) + + // Attempt request without client certificate + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + _, err := client.Do(req) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("tls")) + }) + + It("accepts valid client certificate from the configured CA", func() { + // Create instance identity certificate (need to use the same CA!) + appInstanceCert = &test_util.CertChain{} + // Recreate with SAME CA as configured in GoRouter + *appInstanceCert = test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "app-instance", + AppGUID: "app-guid-123", + SpaceGUID: "space-guid-456", + OrgGUID: "org-guid-789", + }, mtlsDomainCA) + + // Register route on mTLS domain with allowed sources + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "apps": []string{"app-guid-123"}, + }, + ) + + // Configure client to use instance identity cert + clientTLSConfig := &tls.Config{ + RootCAs: testState.client.Transport.(*http.Transport).TLSClientConfig.RootCAs, + Certificates: []tls.Certificate{ + appInstanceCert.TLSCert(), + }, + } + testState.client.Transport.(*http.Transport).TLSClientConfig = clientTLSConfig + + // Make request + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + + body, _ := io.ReadAll(resp.Body) + resp.Body.Close() + Expect(string(body)).To(Equal("backend-response")) + + // Verify backend received the request + Eventually(backendReceivedReqs).Should(Receive()) + }) + + It("rejects client certificate from unknown CA", func() { + // Create certificate from different CA (not the configured mtlsDomainCA) + unknownCert := test_util.CreateInstanceIdentityCert(test_util.InstanceIdentityCertNames{ + CommonName: "app-instance", + AppGUID: "app-guid-123", + }) + + // Register route + testState.register(backendApp, mtlsDomain) + + // Configure client with unknown cert + clientTLSConfig := &tls.Config{ + RootCAs: testState.client.Transport.(*http.Transport).TLSClientConfig.RootCAs, + Certificates: []tls.Certificate{ + unknownCert.TLSCert(), + }, + } + testState.client.Transport.(*http.Transport).TLSClientConfig = clientTLSConfig + + // Make request - should fail TLS handshake + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + _, err := client.Do(req) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("tls")) + }) + }) + + Context("when requests are made to non-mTLS domains", func() { + var regularDomain string + + BeforeEach(func() { + regularDomain = "my-app.apps.internal" + + // Configure only the mTLS domain + testState.cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.mtls.internal", + CACerts: string(mtlsDomainCA.CACertPEM), + ForwardedClientCert: config.SANITIZE_SET, + }, + } + + testState.StartGorouterOrFail() + }) + + It("does not require client certificates", func() { + // Register route on regular domain + testState.register(backendApp, regularDomain) + + // Make request without client certificate (using HTTPS) + req := testState.newGetRequest(fmt.Sprintf("https://%s", regularDomain)) + resp, err := testState.client.Do(req) + Expect(err).NotTo(HaveOccurred()) + defer resp.Body.Close() + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + + body, _ := io.ReadAll(resp.Body) + Expect(string(body)).To(Equal("backend-response")) + }) + }) + }) + + Describe("App-to-App authorization", func() { + var ( + mtlsDomainCA *test_util.CertChain + backendApp *httptest.Server + backendReceivedReqs chan *http.Request + mtlsDomain string + ) + + BeforeEach(func() { + mtlsDomain = "secure-api.apps.mtls.internal" + + // Create CA for mTLS domain + mtlsDomainCA = &test_util.CertChain{} + *mtlsDomainCA = test_util.CreateSignedCertWithRootCA(test_util.CertNames{CommonName: "Diego Instance Identity CA"}) + + // Setup backend app + backendReceivedReqs = make(chan *http.Request, 10) + backendApp = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + backendReceivedReqs <- r + w.WriteHeader(http.StatusOK) + w.Write([]byte("authorized")) + })) + + // Configure GoRouter + testState.cfg.EnableSSL = true + testState.cfg.ClientCertificateValidationString = "request" + testState.cfg.Domains = []config.MtlsDomainConfig{ + { + Domain: "*.apps.mtls.internal", + CACerts: string(mtlsDomainCA.CACertPEM), + ForwardedClientCert: config.SANITIZE_SET, + }, + } + + testState.StartGorouterOrFail() + }) + + AfterEach(func() { + if backendApp != nil { + backendApp.Close() + } + }) + + Describe("app-level authorization", func() { + It("allows requests from apps in the allowed list", func() { + callerAppGUID := "caller-app-guid-123" + + // Register route with app-level allowed sources + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "apps": []string{callerAppGUID, "other-app-guid"}, + }, + ) + + // Create caller certificate + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: callerAppGUID, + SpaceGUID: "caller-space-guid", + OrgGUID: "caller-org-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + + body, _ := io.ReadAll(resp.Body) + resp.Body.Close() + Expect(string(body)).To(Equal("authorized")) + }) + + It("denies requests from apps not in the allowed list", func() { + // Register route with app-level allowed sources + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "apps": []string{"allowed-app-guid"}, + }, + ) + + // Create caller certificate with different app GUID + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "unauthorized-app-guid", + SpaceGUID: "caller-space-guid", + OrgGUID: "caller-org-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusForbidden)) + }) + }) + + Describe("space-level authorization", func() { + It("allows requests from apps in allowed spaces", func() { + callerSpaceGUID := "dev-space-guid" + + // Register route with space-level allowed sources + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "spaces": []string{callerSpaceGUID, "other-space-guid"}, + }, + ) + + // Create caller certificate + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + SpaceGUID: callerSpaceGUID, + OrgGUID: "caller-org-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + + body, _ := io.ReadAll(resp.Body) + resp.Body.Close() + Expect(string(body)).To(Equal("authorized")) + }) + + It("denies requests from apps in non-allowed spaces", func() { + // Register route with space-level allowed sources + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "spaces": []string{"allowed-space-guid"}, + }, + ) + + // Create caller certificate with different space GUID + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + SpaceGUID: "unauthorized-space-guid", + OrgGUID: "caller-org-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusForbidden)) + }) + }) + + Describe("org-level authorization", func() { + It("allows requests from apps in allowed orgs", func() { + callerOrgGUID := "my-org-guid" + + // Register route with org-level allowed sources + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "orgs": []string{callerOrgGUID}, + }, + ) + + // Create caller certificate + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + SpaceGUID: "caller-space-guid", + OrgGUID: callerOrgGUID, + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + }) + + It("denies requests from apps in non-allowed orgs", func() { + // Register route with org-level allowed sources + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "orgs": []string{"allowed-org-guid"}, + }, + ) + + // Create caller certificate with different org GUID + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + SpaceGUID: "caller-space-guid", + OrgGUID: "unauthorized-org-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusForbidden)) + }) + }) + + Describe("multi-level authorization", func() { + It("allows requests if ANY authorization level matches", func() { + // Register route with multiple authorization levels + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "apps": []string{"specific-app-guid"}, + "spaces": []string{"dev-space-guid"}, + "orgs": []string{"my-org-guid"}, + }, + ) + + // Create caller that matches space level but not app level + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "different-app-guid", + SpaceGUID: "dev-space-guid", // Matches allowed space + OrgGUID: "different-org-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request - should succeed because space matches + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + }) + + It("denies requests if NO authorization level matches", func() { + // Register route with multiple authorization levels + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "apps": []string{"allowed-app-guid"}, + "spaces": []string{"allowed-space-guid"}, + "orgs": []string{"allowed-org-guid"}, + }, + ) + + // Create caller that matches none + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "different-app-guid", + SpaceGUID: "different-space-guid", + OrgGUID: "different-org-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request - should fail + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusForbidden)) + }) + }) + + Describe("'any authenticated app' authorization", func() { + It("allows any authenticated app when any=true", func() { + // Register route with any=true + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "any": true, + }, + ) + + // Create arbitrary caller certificate + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "any-app-instance", + AppGUID: "random-app-guid-999", + SpaceGUID: "random-space-guid", + OrgGUID: "random-org-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request - should succeed + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + }) + }) + + Describe("default-deny behavior", func() { + It("allows requests when route policy enforcement is not enabled", func() { + // Register route without route policy scope (enforcement disabled) + // Cloud Controller only sets RoutePolicyScope when the domain is configured + // with --enforce-route-policies flag + testState.register(backendApp, mtlsDomain) + + // Create caller certificate + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request - should succeed (no enforcement, backend handles auth) + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + }) + + It("denies requests when route policies are empty", func() { + // Register route with empty allowed sources + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "apps": []string{}, + "spaces": []string{}, + "orgs": []string{}, + "any": false, + }, + ) + + // Create caller certificate + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request - should fail + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusForbidden)) + }) + }) + + Describe("X-Forwarded-Client-Cert header", func() { + It("forwards sanitized client certificate to backend on mTLS domains", func() { + // Register route with allowed sources + testState.registerWithAccessRules( + backendApp, + mtlsDomain, + map[string]interface{}{ + "apps": []string{"caller-app-guid"}, + }, + ) + + // Create caller certificate + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + SpaceGUID: "caller-space-guid", + OrgGUID: "caller-org-guid", + }, mtlsDomainCA) + + // Configure client + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make request + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", mtlsDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + resp.Body.Close() + + // Check backend received XFCC header + var backendReq *http.Request + Eventually(backendReceivedReqs).Should(Receive(&backendReq)) + Expect(backendReq.Header.Get("X-Forwarded-Client-Cert")).NotTo(BeEmpty()) + }) + }) + + // RFC Scenario: Shared routes with post-selection authorization + // This test validates the expected intermittent 403 behavior described in + // RFC lines 475-517 (Post-Selection Authorization). + Describe("shared routes with scope boundaries (intermittent 403s)", func() { + var ( + sharedDomain string + backendApp1 *httptest.Server + backendApp2 *httptest.Server + app1Requests chan *http.Request + app2Requests chan *http.Request + ) + + BeforeEach(func() { + sharedDomain = "shared.apps.mtls.internal" + app1Requests = make(chan *http.Request, 10) + app2Requests = make(chan *http.Request, 10) + + // Setup two backend apps in DIFFERENT spaces + backendApp1 = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + app1Requests <- r + w.WriteHeader(http.StatusOK) + w.Write([]byte("backend-app-1")) + })) + + backendApp2 = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + app2Requests <- r + w.WriteHeader(http.StatusOK) + w.Write([]byte("backend-app-2")) + })) + }) + + AfterEach(func() { + if backendApp1 != nil { + backendApp1.Close() + } + if backendApp2 != nil { + backendApp2.Close() + } + }) + + Context("when two apps register the same route in different spaces", func() { + It("allows requests to the same space and denies to different space (intermittent 403s)", func() { + // Register SAME route from two different spaces with scope=space + // Backend 1 is in space-alpha + testState.registerWithScopeAndAccessRules( + backendApp1, + sharedDomain, + "space", + map[string]interface{}{ + "any": true, + }, + map[string]string{ + "space_id": "space-alpha", + }, + ) + + // Backend 2 is in space-beta + testState.registerWithScopeAndAccessRules( + backendApp2, + sharedDomain, + "space", + map[string]interface{}{ + "any": true, + }, + map[string]string{ + "space_id": "space-beta", + }, + ) + + // Create caller from space-alpha + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + SpaceGUID: "space-alpha", + OrgGUID: "org-123", + }, mtlsDomainCA) + + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make multiple requests and observe intermittent behavior + successCount := 0 + forbiddenCount := 0 + attempts := 10 + + for i := 0; i < attempts; i++ { + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", sharedDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + + if resp.StatusCode == http.StatusOK { + body, _ := io.ReadAll(resp.Body) + // Should only succeed when routed to space-alpha backend + Expect(string(body)).To(Equal("backend-app-1")) + successCount++ + } else if resp.StatusCode == http.StatusForbidden { + // Expected: post-selection check failed (routed to space-beta backend) + forbiddenCount++ + } + resp.Body.Close() + } + + // Verify we got BOTH outcomes (RFC-compliant intermittent 403s) + // With round-robin load balancing, both endpoints should be hit + Expect(successCount).To(BeNumerically(">", 0), "Should have some successful requests (same-space)") + Expect(forbiddenCount).To(BeNumerically(">", 0), "Should have some 403 responses (cross-space)") + Expect(successCount + forbiddenCount).To(Equal(attempts)) + }) + + It("always succeeds when caller is in same org with scope=org", func() { + // Register SAME route from two different spaces but SAME org with scope=org + // Backend 1 is in org-alpha/space-alpha + testState.registerWithScopeAndAccessRules( + backendApp1, + sharedDomain, + "org", + map[string]interface{}{ + "any": true, + }, + map[string]string{ + "organization_id": "org-alpha", + "space_id": "space-alpha", + }, + ) + + // Backend 2 is in org-alpha/space-beta (same org, different space) + testState.registerWithScopeAndAccessRules( + backendApp2, + sharedDomain, + "org", + map[string]interface{}{ + "any": true, + }, + map[string]string{ + "organization_id": "org-alpha", + "space_id": "space-beta", + }, + ) + + // Create caller from org-alpha + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + SpaceGUID: "space-gamma", // Different space, but same org + OrgGUID: "org-alpha", + }, mtlsDomainCA) + + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make multiple requests - ALL should succeed (same org) + for i := 0; i < 10; i++ { + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", sharedDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusOK)) + resp.Body.Close() + } + }) + + It("always fails when caller is in different org with scope=org", func() { + // Register SAME route from two different orgs with scope=org + // Backend 1 is in org-alpha + testState.registerWithScopeAndAccessRules( + backendApp1, + sharedDomain, + "org", + map[string]interface{}{ + "any": true, + }, + map[string]string{ + "organization_id": "org-alpha", + }, + ) + + // Backend 2 is in org-beta + testState.registerWithScopeAndAccessRules( + backendApp2, + sharedDomain, + "org", + map[string]interface{}{ + "any": true, + }, + map[string]string{ + "organization_id": "org-beta", + }, + ) + + // Create caller from org-gamma (different from both backends) + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "caller-app-guid", + SpaceGUID: "space-123", + OrgGUID: "org-gamma", + }, mtlsDomainCA) + + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make multiple requests - ALL should fail (different org) + for i := 0; i < 10; i++ { + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", sharedDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + Expect(resp.StatusCode).To(Equal(http.StatusForbidden)) + resp.Body.Close() + } + }) + }) + + Context("when shared route has app-specific route policies", func() { + It("allows only the specified app and denies others (per-endpoint rules)", func() { + // Backend 1 allows only "allowed-app-1" + testState.registerWithScopeAndAccessRules( + backendApp1, + sharedDomain, + "any", + map[string]interface{}{ + "apps": []string{"allowed-app-1"}, + }, + nil, + ) + + // Backend 2 allows only "allowed-app-2" + testState.registerWithScopeAndAccessRules( + backendApp2, + sharedDomain, + "any", + map[string]interface{}{ + "apps": []string{"allowed-app-2"}, + }, + nil, + ) + + // Create caller with allowed-app-1 + callerCert := test_util.CreateInstanceIdentityCertWithCA(test_util.InstanceIdentityCertNames{ + CommonName: "caller-app-instance", + AppGUID: "allowed-app-1", + SpaceGUID: "space-123", + OrgGUID: "org-123", + }, mtlsDomainCA) + + testState.client.Transport.(*http.Transport).TLSClientConfig.Certificates = []tls.Certificate{ + callerCert.TLSCert(), + } + + // Make multiple requests + successCount := 0 + forbiddenCount := 0 + attempts := 10 + + for i := 0; i < attempts; i++ { + req, client := testState.newMtlsGetRequest(fmt.Sprintf("https://%s", sharedDomain)) + resp, err := client.Do(req) + Expect(err).NotTo(HaveOccurred()) + + if resp.StatusCode == http.StatusOK { + body, _ := io.ReadAll(resp.Body) + // Should only succeed when routed to backend 1 + Expect(string(body)).To(Equal("backend-app-1")) + successCount++ + } else { + Expect(resp.StatusCode).To(Equal(http.StatusForbidden)) + forbiddenCount++ + } + resp.Body.Close() + } + + // Verify intermittent behavior based on endpoint selection + Expect(successCount).To(BeNumerically(">", 0), "Should succeed when routed to backend-1") + Expect(forbiddenCount).To(BeNumerically(">", 0), "Should fail when routed to backend-2") + }) + }) + }) + }) +}) diff --git a/src/code.cloudfoundry.org/gorouter/mbus/registry_message_test.go b/src/code.cloudfoundry.org/gorouter/mbus/registry_message_test.go index 9162a97e6..948049a1d 100644 --- a/src/code.cloudfoundry.org/gorouter/mbus/registry_message_test.go +++ b/src/code.cloudfoundry.org/gorouter/mbus/registry_message_test.go @@ -60,4 +60,110 @@ var _ = Describe("RegistryMessage", func() { }) }) }) + + Describe("MakeEndpoint with route_policy_scope and route_policy_sources", func() { + var message *RegistryMessage + var payload []byte + + JustBeforeEach(func() { + message = new(RegistryMessage) + err := json.Unmarshal(payload, message) + Expect(err).NotTo(HaveOccurred()) + }) + + Describe("With route_policy_scope=any and no route_policy_sources", func() { + BeforeEach(func() { + payload = []byte(`{ + "app":"app1", + "uris":["test.com"], + "host":"1.2.3.4", + "port":1234, + "tags":{}, + "private_instance_id":"private_instance_id", + "options": { + "route_policy_scope": "any" + } + }`) + }) + + It("parses route_policy_scope correctly with empty sources", func() { + endpoint, err := message.MakeEndpoint(false, "round-robin") + Expect(err).NotTo(HaveOccurred()) + Expect(endpoint.RoutePolicyScope).To(Equal("any")) + Expect(endpoint.RoutePolicies).To(BeEmpty()) + }) + }) + + Describe("With route_policy_scope=org and route_policy_sources listing apps and spaces", func() { + BeforeEach(func() { + payload = []byte(`{ + "app":"app1", + "uris":["test.com"], + "host":"1.2.3.4", + "port":1234, + "tags":{}, + "private_instance_id":"private_instance_id", + "options": { + "route_policy_scope": "org", + "route_policy_sources": "cf:app:app-guid-1,cf:space:space-guid-1,cf:org:org-guid-1" + } + }`) + }) + + It("parses route_policy_scope and route_policy_sources correctly", func() { + endpoint, err := message.MakeEndpoint(false, "round-robin") + Expect(err).NotTo(HaveOccurred()) + Expect(endpoint.RoutePolicyScope).To(Equal("org")) + Expect(endpoint.RoutePolicies).To(ConsistOf( + "cf:app:app-guid-1", + "cf:space:space-guid-1", + "cf:org:org-guid-1", + )) + }) + }) + + Describe("With route_policy_scope=space and cf:any rule", func() { + BeforeEach(func() { + payload = []byte(`{ + "app":"app1", + "uris":["test.com"], + "host":"1.2.3.4", + "port":1234, + "tags":{}, + "private_instance_id":"private_instance_id", + "options": { + "route_policy_scope": "space", + "route_policy_sources": "cf:any" + } + }`) + }) + + It("parses cf:any rule correctly", func() { + endpoint, err := message.MakeEndpoint(false, "round-robin") + Expect(err).NotTo(HaveOccurred()) + Expect(endpoint.RoutePolicyScope).To(Equal("space")) + Expect(endpoint.RoutePolicies).To(ConsistOf("cf:any")) + }) + }) + + Describe("With no route_policy_scope or route_policy_sources", func() { + BeforeEach(func() { + payload = []byte(`{ + "app":"app1", + "uris":["test.com"], + "host":"1.2.3.4", + "port":1234, + "tags":{}, + "private_instance_id":"private_instance_id" + }`) + }) + + It("leaves RoutePolicyScope empty and RoutePolicies nil", func() { + endpoint, err := message.MakeEndpoint(false, "round-robin") + Expect(err).NotTo(HaveOccurred()) + Expect(endpoint.RoutePolicyScope).To(BeEmpty()) + Expect(endpoint.RoutePolicies).To(BeEmpty()) + }) + }) + }) }) diff --git a/src/code.cloudfoundry.org/gorouter/mbus/subscriber.go b/src/code.cloudfoundry.org/gorouter/mbus/subscriber.go index f36659621..9c9f0dca2 100644 --- a/src/code.cloudfoundry.org/gorouter/mbus/subscriber.go +++ b/src/code.cloudfoundry.org/gorouter/mbus/subscriber.go @@ -43,10 +43,33 @@ type RegistryMessage struct { type RegistryMessageOpts struct { LoadBalancingAlgorithm string `json:"loadbalancing"` HashHeaderName string `json:"hash_header"` - HashBalance float64 `json:"hash_balance,string"` + HashBalance float64 `json:"hash_balance"` + // RFC route policy options (from Cloud Controller via Diego sync) + RoutePolicyScope string `json:"route_policy_scope,omitempty"` + RoutePolicySources string `json:"route_policy_sources,omitempty"` } -func (rm *RegistryMessage) makeEndpoint(http2Enabled bool, globalRoutingAlgo string) (*route.Endpoint, error) { +// parseCommaSeparatedSources splits a comma-separated string into a slice of sources. +// Returns nil if the input is empty. +func parseCommaSeparatedSources(s string) []string { + if s == "" { + return nil + } + parts := strings.Split(s, ",") + result := make([]string, 0, len(parts)) + for _, p := range parts { + trimmed := strings.TrimSpace(p) + if trimmed != "" { + result = append(result, trimmed) + } + } + if len(result) == 0 { + return nil + } + return result +} + +func (rm *RegistryMessage) MakeEndpoint(http2Enabled bool, globalRoutingAlgo string) (*route.Endpoint, error) { port, useTLS, err := rm.port() if err != nil { return nil, err @@ -85,6 +108,8 @@ func (rm *RegistryMessage) makeEndpoint(http2Enabled bool, globalRoutingAlgo str LoadBalancingAlgorithm: lbAlgo, HashHeaderName: rm.Options.HashHeaderName, HashBalanceFactor: rm.Options.HashBalance, + RoutePolicyScope: rm.Options.RoutePolicyScope, + RoutePolicies: parseCommaSeparatedSources(rm.Options.RoutePolicySources), }), nil } @@ -250,7 +275,7 @@ func (s *Subscriber) subscribeRoutes() (*nats.Subscription, error) { } func (s *Subscriber) registerEndpoint(msg *RegistryMessage) { - endpoint, err := msg.makeEndpoint(s.http2Enabled, s.globalRoutingAlgo) + endpoint, err := msg.MakeEndpoint(s.http2Enabled, s.globalRoutingAlgo) if err != nil { s.logger.Error("Unable to register route", log.ErrAttr(err), @@ -265,7 +290,7 @@ func (s *Subscriber) registerEndpoint(msg *RegistryMessage) { } func (s *Subscriber) unregisterEndpoint(msg *RegistryMessage) { - endpoint, err := msg.makeEndpoint(s.http2Enabled, s.globalRoutingAlgo) + endpoint, err := msg.MakeEndpoint(s.http2Enabled, s.globalRoutingAlgo) if err != nil { s.logger.Error("Unable to unregister route", log.ErrAttr(err), diff --git a/src/code.cloudfoundry.org/gorouter/proxy/proxy.go b/src/code.cloudfoundry.org/gorouter/proxy/proxy.go index 790eca7b7..907efa8e4 100644 --- a/src/code.cloudfoundry.org/gorouter/proxy/proxy.go +++ b/src/code.cloudfoundry.org/gorouter/proxy/proxy.go @@ -115,6 +115,15 @@ func NewProxy( IsInstrumented: cfg.SendHttpStartStopClientEvent, } + // Create post-selection authorization pipeline + // This runs after endpoint selection in the round tripper to enforce + // RFC-compliant strict scope and route policies checking. + postSelectionPipeline := handlers.NewPostSelectionPipeline( + logger, + handlers.NewMtlsScopeAuth(cfg, logger), + handlers.NewMtlsRoutePoliciesAuth(cfg, logger), + ) + prt := round_tripper.NewProxyRoundTripper( roundTripperFactory, fails.RetriableClassifiers, @@ -126,6 +135,7 @@ func NewProxy( }, routeServicesTransport, cfg, + postSelectionPipeline, ) rproxy := &httputil.ReverseProxy{ @@ -134,6 +144,9 @@ func NewProxy( FlushInterval: 50 * time.Millisecond, BufferPool: p.bufferPool, ModifyResponse: p.modifyResponse, + ErrorHandler: func(rw http.ResponseWriter, req *http.Request, err error) { + handleReverseProxyError(logger, rw, err) + }, } routeServiceHandler := handlers.NewRouteService(routeServiceConfig, registry, logger, errorWriter) @@ -168,13 +181,17 @@ func NewProxy( n.Use(handlers.NewProtocolCheck(logger, errorWriter, cfg.EnableHTTP2)) n.Use(handlers.NewLookup(registry, reporter, logger, errorWriter, cfg.EmptyPoolResponseCode503)) n.Use(handlers.NewMaxRequestSize(cfg, logger)) + n.Use(handlers.NewMtlsSniCheck(cfg, logger)) n.Use(handlers.NewClientCert( SkipSanitize(routeServiceHandler.(*handlers.RouteService)), ForceDeleteXFCCHeader(routeServiceHandler.(*handlers.RouteService), cfg.ForwardedClientCert, logger), cfg.ForwardedClientCert, + cfg, logger, errorWriter, )) + n.Use(handlers.NewCfIdentity(cfg)) + n.Use(handlers.NewMtlsPreAuth(cfg, logger)) n.Use(handlers.NewHopByHop(cfg, logger)) n.Use(&handlers.XForwardedProto{ SkipSanitization: SkipSanitizeXFP(routeServiceHandler.(*handlers.RouteService)), @@ -287,6 +304,26 @@ func escapePathAndPreserveSlashes(unescaped string) string { return escapedPath } +// handleReverseProxyError writes an appropriate HTTP error response for errors +// returned by the backend round tripper. AuthErrors produce the HTTP status +// code embedded in the error (typically 403 Forbidden). All other errors +// produce a generic 502 Bad Gateway without leaking internal error details. +func handleReverseProxyError(logger *slog.Logger, rw http.ResponseWriter, err error) { + if authErr, ok := err.(*handlers.AuthError); ok { + // Use ClientMessage() to avoid leaking internal rule names or caller identities. + rw.WriteHeader(authErr.HTTPStatus) + if _, writeErr := rw.Write([]byte(authErr.ClientMessage())); writeErr != nil { + logger.Error("failed to write auth error response", log.ErrAttr(writeErr)) + } + return + } + // Use a generic message to avoid leaking internal error details to the client. + rw.WriteHeader(http.StatusBadGateway) + if _, writeErr := rw.Write([]byte(http.StatusText(http.StatusBadGateway))); writeErr != nil { + logger.Error("failed to write error response", log.ErrAttr(writeErr)) + } +} + // RouteServiceDialControl checks if the address is allowed based on the block list. func RouteServiceDialControl(routeServiceConfig *routeservice.RouteServiceConfig) func(network, address string, c syscall.RawConn) error { return func(network, address string, c syscall.RawConn) error { diff --git a/src/code.cloudfoundry.org/gorouter/proxy/proxy_error_handler_test.go b/src/code.cloudfoundry.org/gorouter/proxy/proxy_error_handler_test.go new file mode 100644 index 000000000..3c6840e64 --- /dev/null +++ b/src/code.cloudfoundry.org/gorouter/proxy/proxy_error_handler_test.go @@ -0,0 +1,70 @@ +package proxy + +import ( + "log/slog" + "net/http" + "net/http/httptest" + "testing" + + "code.cloudfoundry.org/gorouter/handlers" +) + +func TestHandleReverseProxyError_AuthError_Writes403WithGenericMessage(t *testing.T) { + rw := httptest.NewRecorder() + authErr := handlers.NewAuthError("test:scope:rule", "caller not authorized") + logger := slog.Default() + + handleReverseProxyError(logger, rw, authErr) + + if rw.Code != http.StatusForbidden { + t.Errorf("expected status 403, got %d", rw.Code) + } + body := rw.Body.String() + if body != "Forbidden" { + t.Errorf("expected body %q, got %q", "Forbidden", body) + } +} + +func TestHandleReverseProxyError_AuthErrorCustomStatus_WritesCorrectStatus(t *testing.T) { + rw := httptest.NewRecorder() + authErr := handlers.NewAuthErrorWithStatus("test:rule", "misdirected", http.StatusMisdirectedRequest) + logger := slog.Default() + + handleReverseProxyError(logger, rw, authErr) + + if rw.Code != http.StatusMisdirectedRequest { + t.Errorf("expected status 421, got %d", rw.Code) + } +} + +func TestHandleReverseProxyError_NonAuthError_Writes502WithGenericMessage(t *testing.T) { + rw := httptest.NewRecorder() + logger := slog.Default() + + handleReverseProxyError(logger, rw, http.ErrAbortHandler) + + if rw.Code != http.StatusBadGateway { + t.Errorf("expected status 502, got %d", rw.Code) + } + body := rw.Body.String() + if body != "Bad Gateway" { + t.Errorf("expected body %q, got %q", "Bad Gateway", body) + } +} + +func TestHandleReverseProxyError_NonAuthError_DoesNotLeakInternalMessage(t *testing.T) { + rw := httptest.NewRecorder() + logger := slog.Default() + sensitiveErr := &sensitiveTestError{msg: "internal DB connection pool exhausted at 192.168.1.5:5432"} + + handleReverseProxyError(logger, rw, sensitiveErr) + + body := rw.Body.String() + if body == sensitiveErr.Error() { + t.Errorf("response body must not contain internal error message, got %q", body) + } +} + +type sensitiveTestError struct{ msg string } + +func (e *sensitiveTestError) Error() string { return e.msg } diff --git a/src/code.cloudfoundry.org/gorouter/proxy/round_tripper/proxy_round_tripper.go b/src/code.cloudfoundry.org/gorouter/proxy/round_tripper/proxy_round_tripper.go index cbe223136..6348d27bd 100644 --- a/src/code.cloudfoundry.org/gorouter/proxy/round_tripper/proxy_round_tripper.go +++ b/src/code.cloudfoundry.org/gorouter/proxy/round_tripper/proxy_round_tripper.go @@ -76,6 +76,7 @@ func NewProxyRoundTripper( errHandler errorHandler, routeServicesTransport http.RoundTripper, cfg *config.Config, + postSelectionPipeline *handlers.PostSelectionPipeline, ) ProxyRoundTripper { return &roundTripper{ @@ -86,6 +87,7 @@ func NewProxyRoundTripper( errorHandler: errHandler, routeServicesTransport: routeServicesTransport, config: cfg, + postSelectionPipeline: postSelectionPipeline, } } @@ -97,6 +99,7 @@ type roundTripper struct { errorHandler errorHandler routeServicesTransport http.RoundTripper config *config.Config + postSelectionPipeline *handlers.PostSelectionPipeline } func (rt *roundTripper) RoundTrip(originalRequest *http.Request) (*http.Response, error) { @@ -193,6 +196,35 @@ func (rt *roundTripper) RoundTrip(originalRequest *http.Request) (*http.Response triedEndpoints[endpoint.CanonicalAddr()] = true reqInfo.RouteEndpoint = endpoint + // ── Post-selection authorization ────────────────────────────────────── + // Run post-selection authorization pipeline after endpoint selection but + // before making the backend request. This enforces RFC-compliant strict + // post-selection scope and route policies checking. + if rt.postSelectionPipeline != nil { + if authErr := rt.postSelectionPipeline.Run(endpoint, reqInfo); authErr != nil { + // Authorization failed - populate AuthResult for access logs + if authError, ok := authErr.(*handlers.AuthError); ok { + reqInfo.AuthResult = &handlers.AuthResult{ + Outcome: "denied", + Rule: authError.Rule, + DeniedReason: authError.Reason, + } + + // Return authorization error - will be converted to 403 by error handler + return nil, authErr + } + + // Unknown error type - still populate AuthResult for logging + reqInfo.AuthResult = &handlers.AuthResult{ + Outcome: "denied", + Rule: "unknown_error", + DeniedReason: authErr.Error(), + } + + return nil, authErr + } + } + logger.Debug("backend", slog.Int("attempt", attempt)) if endpoint.IsTLS() { request.URL.Scheme = "https" @@ -337,7 +369,13 @@ func (rt *roundTripper) RoundTrip(originalRequest *http.Request) (*http.Response } if err != nil { - rt.errorHandler.HandleError(reqInfo.ProxyResponseWriter, err) + // For AuthErrors, skip the internal error handler so the ReverseProxy's + // ErrorHandler can write the correct HTTP status (e.g. 403 Forbidden). + // Running the internal handler first would write a 502 and call Done(), + // committing the response before the ReverseProxy's ErrorHandler runs. + if _, isAuthErr := err.(*handlers.AuthError); !isAuthErr { + rt.errorHandler.HandleError(reqInfo.ProxyResponseWriter, err) + } if handlers.IsWebSocketUpgrade(request) { rt.combinedReporter.CaptureWebSocketFailure() } diff --git a/src/code.cloudfoundry.org/gorouter/proxy/round_tripper/proxy_round_tripper_test.go b/src/code.cloudfoundry.org/gorouter/proxy/round_tripper/proxy_round_tripper_test.go index fa59b63b3..f3cfe830c 100644 --- a/src/code.cloudfoundry.org/gorouter/proxy/round_tripper/proxy_round_tripper_test.go +++ b/src/code.cloudfoundry.org/gorouter/proxy/round_tripper/proxy_round_tripper_test.go @@ -24,6 +24,7 @@ import ( "code.cloudfoundry.org/gorouter/config" sharedfakes "code.cloudfoundry.org/gorouter/fakes" "code.cloudfoundry.org/gorouter/handlers" + handlersfakes "code.cloudfoundry.org/gorouter/handlers/fakes" "code.cloudfoundry.org/gorouter/metrics/fakes" "code.cloudfoundry.org/gorouter/proxy/fails" errorClassifierFakes "code.cloudfoundry.org/gorouter/proxy/fails/fakes" @@ -172,6 +173,7 @@ var _ = Describe("ProxyRoundTripper", func() { errorHandler, routeServicesTransport, cfg, + nil, // postSelectionPipeline - not testing mTLS auth in these tests ) }) @@ -3072,6 +3074,96 @@ var _ = Describe("ProxyRoundTripper", func() { }) }) }) + Context("post-selection authorization pipeline", func() { + var fakeHandler *handlersfakes.FakePostSelectionHandler + + BeforeEach(func() { + fakeHandler = &handlersfakes.FakePostSelectionHandler{} + }) + + JustBeforeEach(func() { + pipeline := handlers.NewPostSelectionPipeline(logger.Logger, fakeHandler) + proxyRoundTripper = round_tripper.NewProxyRoundTripper( + roundTripperFactory, + retriableClassifier, + logger.Logger, + combinedReporter, + errorHandler, + routeServicesTransport, + cfg, + pipeline, + ) + }) + + Context("when the pipeline returns an AuthError", func() { + var authErr *handlers.AuthError + + BeforeEach(func() { + authErr = handlers.NewAuthError("test:scope:rule", "caller app not in allowed scope") + fakeHandler.CheckReturns(authErr) + }) + + It("returns the AuthError from RoundTrip", func() { + _, err := proxyRoundTripper.RoundTrip(req) + Expect(err).To(Equal(authErr)) + }) + + It("populates AuthResult on reqInfo with denied outcome", func() { + _, _ = proxyRoundTripper.RoundTrip(req) + Expect(reqInfo.AuthResult).ToNot(BeNil()) + Expect(reqInfo.AuthResult.Outcome).To(Equal("denied")) + Expect(reqInfo.AuthResult.Rule).To(Equal("test:scope:rule")) + Expect(reqInfo.AuthResult.DeniedReason).To(Equal("caller app not in allowed scope")) + }) + + It("does NOT call the internal error handler so the ReverseProxy ErrorHandler can write 403", func() { + _, _ = proxyRoundTripper.RoundTrip(req) + Expect(errorHandler.HandleErrorCallCount()).To(Equal(0)) + }) + }) + + Context("when the pipeline returns an unknown (non-AuthError) error", func() { + var unknownErr error + + BeforeEach(func() { + unknownErr = errors.New("unexpected pipeline failure") + fakeHandler.CheckReturns(unknownErr) + }) + + It("returns the error from RoundTrip", func() { + _, err := proxyRoundTripper.RoundTrip(req) + Expect(err).To(Equal(unknownErr)) + }) + + It("populates AuthResult with unknown_error rule", func() { + _, _ = proxyRoundTripper.RoundTrip(req) + Expect(reqInfo.AuthResult).ToNot(BeNil()) + Expect(reqInfo.AuthResult.Outcome).To(Equal("denied")) + Expect(reqInfo.AuthResult.Rule).To(Equal("unknown_error")) + Expect(reqInfo.AuthResult.DeniedReason).To(Equal("unexpected pipeline failure")) + }) + + It("does NOT call the internal error handler for non-AuthError pipeline failures", func() { + _, _ = proxyRoundTripper.RoundTrip(req) + Expect(errorHandler.HandleErrorCallCount()).To(Equal(0)) + }) + }) + + Context("when the pipeline passes (returns nil)", func() { + BeforeEach(func() { + transport.RoundTripReturns(&http.Response{StatusCode: http.StatusOK}, nil) + fakeHandler.CheckReturns(nil) + }) + + It("proceeds to the backend and returns the response", func() { + res, err := proxyRoundTripper.RoundTrip(req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.StatusCode).To(Equal(http.StatusOK)) + Expect(transport.RoundTripCallCount()).To(Equal(1)) + }) + }) + }) + Context("CancelRequest", func() { It("can cancel requests", func() { reqInfo.RouteEndpoint = endpoint diff --git a/src/code.cloudfoundry.org/gorouter/route/pool.go b/src/code.cloudfoundry.org/gorouter/route/pool.go index cff30523b..0eabe03e5 100644 --- a/src/code.cloudfoundry.org/gorouter/route/pool.go +++ b/src/code.cloudfoundry.org/gorouter/route/pool.go @@ -63,6 +63,14 @@ type Stats struct { NumberConnections *Counter } +// RoutePolicyScopeAny, RoutePolicyScopeOrg, RoutePolicyScopeSpace are the valid values for RoutePolicyScope. +// They correspond to the route_policies_scope field in Cloud Controller. +const ( + RoutePolicyScopeAny = "any" + RoutePolicyScopeOrg = "org" + RoutePolicyScopeSpace = "space" +) + func NewStats() *Stats { return &Stats{ NumberConnections: &Counter{}, @@ -118,6 +126,12 @@ type Endpoint struct { LoadBalancingAlgorithm string HashHeaderName string HashBalanceFactor float64 + // RoutePolicyScope is the operator-level scope boundary: "any", "org", or "space". + // Non-empty means access control is enforced for this endpoint's route. + RoutePolicyScope string + // RoutePolicies is the list of parsed sources (e.g. "cf:app:", "cf:space:", + // "cf:org:", "cf:any"). Empty with a non-empty RoutePolicyScope means default-deny. + RoutePolicies []string } func (e *Endpoint) RoundTripper() ProxyRoundTripper { @@ -163,7 +177,9 @@ func (e *Endpoint) Equal(e2 *Endpoint) bool { e.LoadBalancingAlgorithm == e2.LoadBalancingAlgorithm && e.HashHeaderName == e2.HashHeaderName && e.HashBalanceFactor == e2.HashBalanceFactor && - maps.Equal(e.Tags, e2.Tags) + maps.Equal(e.Tags, e2.Tags) && + e.RoutePolicyScope == e2.RoutePolicyScope && + slices.Equal(e.RoutePolicies, e2.RoutePolicies) } @@ -210,6 +226,13 @@ type EndpointPool struct { LoadBalancingAlgorithm string HashRoutingProperties *HashRoutingProperties HashLookupTable MaglevLookup + + // routePolicyScope is the operator-level scope boundary: "any", "org", or "space". + // Stored at pool level because all endpoints on the same route share the same policies. + routePolicyScope string + // routePolicies is the list of parsed sources (e.g. "cf:app:", "cf:space:", + // "cf:org:", "cf:any"). Empty with a non-empty routePolicyScope means default-deny. + routePolicies []string } type EndpointOpts struct { @@ -231,6 +254,12 @@ type EndpointOpts struct { LoadBalancingAlgorithm string HashHeaderName string HashBalanceFactor float64 + // RoutePolicyScope is the operator-level scope: "any", "org", or "space". + // Non-empty means enforcement is active for this route. + RoutePolicyScope string + // RoutePolicies are the parsed sources for this route. + // Empty + non-empty RoutePolicyScope means default-deny. + RoutePolicies []string } func NewEndpoint(opts *EndpointOpts) *Endpoint { @@ -251,6 +280,8 @@ func NewEndpoint(opts *EndpointOpts) *Endpoint { IsolationSegment: opts.IsolationSegment, UpdatedAt: opts.UpdatedAt, LoadBalancingAlgorithm: opts.LoadBalancingAlgorithm, + RoutePolicyScope: opts.RoutePolicyScope, + RoutePolicies: opts.RoutePolicies, } if opts.LoadBalancingAlgorithm == config.LOAD_BALANCE_HB && opts.HashHeaderName != "" { // BalanceFactor is optional @@ -369,6 +400,8 @@ func (p *EndpointPool) Put(endpoint *Endpoint) PoolPutResult { p.RouteSvcUrl = e.endpoint.RouteServiceUrl p.setPoolLoadBalancingAlgorithm(e.endpoint) + p.routePolicyScope = endpoint.RoutePolicyScope + p.routePolicies = endpoint.RoutePolicies e.updated = time.Now() if p.LoadBalancingAlgorithm == config.LOAD_BALANCE_HB { p.HashLookupTable.Add(e.endpoint.PrivateInstanceId) @@ -392,6 +425,8 @@ func (p *EndpointPool) Put(endpoint *Endpoint) PoolPutResult { p.RouteSvcUrl = e.endpoint.RouteServiceUrl p.setPoolLoadBalancingAlgorithm(e.endpoint) + p.routePolicyScope = endpoint.RoutePolicyScope + p.routePolicies = endpoint.RoutePolicies if p.LoadBalancingAlgorithm == config.LOAD_BALANCE_HB { p.HashLookupTable.Add(e.endpoint.PrivateInstanceId) } @@ -579,6 +614,40 @@ func (p *EndpointPool) IsEmpty() bool { return l == 0 } +// RoutePolicyScope returns the route policy scope for this pool. +// All endpoints in a pool share the same route policy scope since they represent +// instances of the same application route registered with the same options. +// Returns empty string if enforcement is not active. +func (p *EndpointPool) RoutePolicyScope() string { + p.Lock() + defer p.Unlock() + + return p.routePolicyScope +} + +// RoutePolicies returns the route policies for this pool. +// All endpoints in a pool share the same route policies. +// Returns nil if no policies are configured. +func (p *EndpointPool) RoutePolicies() []string { + p.Lock() + defer p.Unlock() + + return p.routePolicies +} + +// ApplicationId returns the ApplicationId from the first endpoint in the pool. +// All endpoints in a pool should have the same ApplicationId. +func (p *EndpointPool) ApplicationId() string { + p.Lock() + defer p.Unlock() + + if len(p.endpoints) == 0 { + return "" + } + + return p.endpoints[0].endpoint.ApplicationId +} + func (p *EndpointPool) NextIndex() int { if p.NextIdx == -1 { p.NextIdx = p.random.Intn(len(p.endpoints)) @@ -740,6 +809,8 @@ func (e *Endpoint) MarshalJSON() ([]byte, error) { LoadBalancingAlgorithm string `json:"load_balancing_algorithm,omitempty"` HashHeader string `json:"hash_header,omitempty"` HashBalance *float64 `json:"hash_balance,omitempty"` // omitempty on a float64 field will omit the field when the value is 0.0, to keep 0 use pointer of float64 + RoutePolicyScope string `json:"route_policy_scope,omitempty"` + RoutePolicies []string `json:"route_policies,omitempty"` } jsonObj.Address = e.addr @@ -754,6 +825,8 @@ func (e *Endpoint) MarshalJSON() ([]byte, error) { jsonObj.ServerCertDomainSAN = e.ServerCertDomainSAN jsonObj.LoadBalancingAlgorithm = e.LoadBalancingAlgorithm jsonObj.HashHeader = e.HashHeaderName + jsonObj.RoutePolicyScope = e.RoutePolicyScope + jsonObj.RoutePolicies = e.RoutePolicies // marshal balance factor only if load balancing algorithm is hash-based if e.LoadBalancingAlgorithm == config.LOAD_BALANCE_HB { diff --git a/src/code.cloudfoundry.org/gorouter/route/pool_test.go b/src/code.cloudfoundry.org/gorouter/route/pool_test.go index db748278a..c4ae1f5e1 100644 --- a/src/code.cloudfoundry.org/gorouter/route/pool_test.go +++ b/src/code.cloudfoundry.org/gorouter/route/pool_test.go @@ -1082,6 +1082,53 @@ var _ = Describe("EndpointPool", func() { }) }) + Context("when endpoints have route policy fields", func() { + It("marshals json with route_policy_scope and route_policies", func() { + e := route.NewEndpoint(&route.EndpointOpts{ + Host: "1.2.3.4", + Port: 5678, + Protocol: "http2", + StaleThresholdInSeconds: -1, + RoutePolicyScope: route.RoutePolicyScopeOrg, + RoutePolicies: []string{"cf:org:org-guid-1", "cf:app:app-guid-1"}, + }) + pool.Put(e) + + json, err := pool.MarshalJSON() + Expect(err).ToNot(HaveOccurred()) + Expect(string(json)).To(Equal(`[{"address":"1.2.3.4:5678","availability_zone":"","protocol":"http2","tls":false,"ttl":-1,"tags":null,"route_policy_scope":"org","route_policies":["cf:org:org-guid-1","cf:app:app-guid-1"]}]`)) + }) + + It("marshals json with route_policy_scope only", func() { + e := route.NewEndpoint(&route.EndpointOpts{ + Host: "1.2.3.4", + Port: 5678, + Protocol: "http2", + StaleThresholdInSeconds: -1, + RoutePolicyScope: route.RoutePolicyScopeSpace, + }) + pool.Put(e) + + json, err := pool.MarshalJSON() + Expect(err).ToNot(HaveOccurred()) + Expect(string(json)).To(Equal(`[{"address":"1.2.3.4:5678","availability_zone":"","protocol":"http2","tls":false,"ttl":-1,"tags":null,"route_policy_scope":"space"}]`)) + }) + + It("omits route policy fields when empty", func() { + e := route.NewEndpoint(&route.EndpointOpts{ + Host: "1.2.3.4", + Port: 5678, + Protocol: "http2", + StaleThresholdInSeconds: -1, + }) + pool.Put(e) + + json, err := pool.MarshalJSON() + Expect(err).ToNot(HaveOccurred()) + Expect(string(json)).To(Equal(`[{"address":"1.2.3.4:5678","availability_zone":"","protocol":"http2","tls":false,"ttl":-1,"tags":null}]`)) + }) + }) + Describe("ProcessId", func() { Context("when there are no tags", func() { It("returns an empty string", func() { @@ -1132,4 +1179,111 @@ var _ = Describe("EndpointPool", func() { }) }) }) + + Describe("RoutePolicyScope and RoutePolicies", func() { + var pool *route.EndpointPool + + BeforeEach(func() { + pool = route.NewPool(&route.PoolOpts{ + Host: "backend.apps.internal", + }) + }) + + It("returns empty scope and nil policies for a fresh pool", func() { + Expect(pool.RoutePolicyScope()).To(Equal("")) + Expect(pool.RoutePolicies()).To(BeNil()) + }) + + It("returns the scope from the most recently Put endpoint", func() { + endpoint := route.NewEndpoint(&route.EndpointOpts{ + Host: "10.0.0.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + }) + pool.Put(endpoint) + + Expect(pool.RoutePolicyScope()).To(Equal(route.RoutePolicyScopeOrg)) + }) + + It("returns the policies from the most recently Put endpoint", func() { + endpoint := route.NewEndpoint(&route.EndpointOpts{ + Host: "10.0.0.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + RoutePolicies: []string{"cf:org:org-guid-1", "cf:app:app-guid-1"}, + }) + pool.Put(endpoint) + + Expect(pool.RoutePolicies()).To(Equal([]string{"cf:org:org-guid-1", "cf:app:app-guid-1"})) + }) + + It("updates scope and policies when a new endpoint is Put", func() { + endpoint1 := route.NewEndpoint(&route.EndpointOpts{ + Host: "10.0.0.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + RoutePolicies: []string{"cf:org:org-guid-1"}, + }) + pool.Put(endpoint1) + + endpoint2 := route.NewEndpoint(&route.EndpointOpts{ + Host: "10.0.0.2", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeSpace, + RoutePolicies: []string{"cf:space:space-guid-1", "cf:app:app-guid-2"}, + }) + pool.Put(endpoint2) + + Expect(pool.RoutePolicyScope()).To(Equal(route.RoutePolicyScopeSpace)) + Expect(pool.RoutePolicies()).To(Equal([]string{"cf:space:space-guid-1", "cf:app:app-guid-2"})) + }) + + It("retains scope and policies after all endpoints are removed", func() { + endpoint := route.NewEndpoint(&route.EndpointOpts{ + Host: "10.0.0.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + RoutePolicies: []string{"cf:org:org-guid-1"}, + }) + pool.Put(endpoint) + pool.Remove(endpoint) + + Expect(pool.RoutePolicyScope()).To(Equal(route.RoutePolicyScopeOrg)) + Expect(pool.RoutePolicies()).To(Equal([]string{"cf:org:org-guid-1"})) + }) + + It("updates scope and policies when an existing endpoint is re-Put with new values", func() { + endpoint := route.NewEndpoint(&route.EndpointOpts{ + Host: "10.0.0.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + RoutePolicies: []string{"cf:org:org-guid-1"}, + }) + pool.Put(endpoint) + + updatedEndpoint := route.NewEndpoint(&route.EndpointOpts{ + Host: "10.0.0.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeSpace, + RoutePolicies: []string{"cf:space:space-guid-1"}, + }) + pool.Put(updatedEndpoint) + + Expect(pool.RoutePolicyScope()).To(Equal(route.RoutePolicyScopeSpace)) + Expect(pool.RoutePolicies()).To(Equal([]string{"cf:space:space-guid-1"})) + }) + + It("handles empty policies with non-empty scope (default-deny)", func() { + endpoint := route.NewEndpoint(&route.EndpointOpts{ + Host: "10.0.0.1", + Port: 8080, + RoutePolicyScope: route.RoutePolicyScopeOrg, + RoutePolicies: []string{}, + }) + pool.Put(endpoint) + + Expect(pool.RoutePolicyScope()).To(Equal(route.RoutePolicyScopeOrg)) + Expect(pool.RoutePolicies()).To(Equal([]string{})) + }) + }) }) diff --git a/src/code.cloudfoundry.org/gorouter/router/router.go b/src/code.cloudfoundry.org/gorouter/router/router.go index 42b79b65e..5aff90b99 100644 --- a/src/code.cloudfoundry.org/gorouter/router/router.go +++ b/src/code.cloudfoundry.org/gorouter/router/router.go @@ -3,6 +3,7 @@ package router import ( "bytes" "compress/zlib" + "context" "crypto/tls" "crypto/x509" "encoding/json" @@ -215,6 +216,12 @@ func (r *Router) Run(signals <-chan os.Signal, ready chan<- struct{}) error { IdleTimeout: r.config.FrontendIdleTimeout, ReadHeaderTimeout: r.config.ReadHeaderTimeout, MaxHeaderBytes: MAX_HEADER_BYTES, + // ConnContext injects a mutable *TLSConnState per connection so that + // getTLSConfigForClient can populate it during the TLS handshake and + // the authorization handler can read it later. + ConnContext: func(ctx context.Context, c net.Conn) context.Context { + return handlers.SetTLSConnState(ctx, &handlers.TLSConnState{}) + }, } err = r.serveHTTP(server, r.errChan) @@ -291,7 +298,8 @@ func (r *Router) serveHTTPS(server *http.Server, errChan chan error) error { return nil } - tlsConfig := &tls.Config{ + // Base TLS config for non-mTLS domains + baseTlsConfig := &tls.Config{ Certificates: r.config.SSLCertificates, CipherSuites: r.config.CipherSuites, MinVersion: r.config.MinTLSVersion, @@ -301,18 +309,25 @@ func (r *Router) serveHTTPS(server *http.Server, errChan chan error) error { } if r.config.VerifyClientCertificatesBasedOnProvidedMetadata && r.config.VerifyClientCertificateMetadataRules != nil { - tlsConfig.VerifyPeerCertificate = r.verifyMtlsMetadata + baseTlsConfig.VerifyPeerCertificate = r.verifyMtlsMetadata } if r.config.EnableHTTP2 { - tlsConfig.NextProtos = []string{"h2", "http/1.1"} + baseTlsConfig.NextProtos = []string{"h2", "http/1.1"} } // Although this functionality is deprecated there is no intention to remove it from the stdlib // due to the Go 1 compatibility promise. We rely on it to prefer more specific matches (a full // SNI match over wildcard matches) instead of relying on the order of certificates. //lint:ignore SA1019 - see ^^ - tlsConfig.BuildNameToCertificate() + baseTlsConfig.BuildNameToCertificate() + + // Wrap with GetConfigForClient for per-domain mTLS + tlsConfig := &tls.Config{ + GetConfigForClient: func(hello *tls.ClientHelloInfo) (*tls.Config, error) { + return r.getTLSConfigForClient(hello, baseTlsConfig) + }, + } listener, err := net.Listen("tcp", fmt.Sprintf(":%d", r.config.SSLPort)) if err != nil { @@ -353,6 +368,37 @@ func (r *Router) verifyMtlsMetadata(_ [][]byte, chains [][]*x509.Certificate) er return nil } +// getTLSConfigForClient returns appropriate TLS config based on SNI (Server Name Indication) +// For mTLS domains, it requires and verifies client certificates using domain-specific CA pool +// For regular domains, it uses the base TLS configuration +func (r *Router) getTLSConfigForClient(hello *tls.ClientHelloInfo, baseConfig *tls.Config) (*tls.Config, error) { + serverName := hello.ServerName + + // Populate TLSConnState in the connection context (set by ConnContext above). + // The pointer was allocated in ConnContext; we mutate it here during the handshake. + if connState, ok := hello.Context().Value(handlers.TLSConnStateKey{}).(*handlers.TLSConnState); ok && connState != nil { + connState.SNI = serverName + } + + mtlsDomainConfig := r.config.GetMtlsDomainConfig(serverName) + if mtlsDomainConfig == nil { + // Not an mTLS domain, use base config + return baseConfig, nil + } + + // mTLS domain — require client certificate and record the state. + if connState, ok := hello.Context().Value(handlers.TLSConnStateKey{}).(*handlers.TLSConnState); ok && connState != nil { + connState.ClientCertRequired = true + connState.MtlsDomain = mtlsDomainConfig.Domain + } + + mtlsConfig := baseConfig.Clone() + mtlsConfig.ClientAuth = tls.RequireAndVerifyClientCert + mtlsConfig.ClientCAs = mtlsDomainConfig.CAPool + + return mtlsConfig, nil +} + func (r *Router) serveHTTP(server *http.Server, errChan chan error) error { if r.config.DisableHTTP { r.logger.Info("tcp-listener-disabled") diff --git a/src/code.cloudfoundry.org/gorouter/test_util/helpers.go b/src/code.cloudfoundry.org/gorouter/test_util/helpers.go index c98e341b8..d489af656 100644 --- a/src/code.cloudfoundry.org/gorouter/test_util/helpers.go +++ b/src/code.cloudfoundry.org/gorouter/test_util/helpers.go @@ -738,3 +738,130 @@ func CreateInvalidCertAndRule(cn string, invalidSubjects []string) ([]*x509.Cert // Return leaf + CA in chain return []*x509.Certificate{x509Leaf, x509CA}, rule, nil } + +// InstanceIdentityCertNames contains identity information for instance identity certificates +type InstanceIdentityCertNames struct { + CommonName string + AppGUID string // Required - will be added as OU "app:" + SpaceGUID string // Optional - will be added as OU "space:" + OrgGUID string // Optional - will be added as OU "organization:" + SANs SubjectAltNames +} + +// CreateInstanceIdentityCert creates a certificate chain with instance identity +// information embedded in OrganizationalUnit fields, matching Diego's format +func CreateInstanceIdentityCert(certNames InstanceIdentityCertNames) CertChain { + rootPrivateKey, rootCADER := CreateCertDER("Diego Instance Identity CA") + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + Expect(err).ToNot(HaveOccurred()) + + // Build OrganizationalUnit slice with instance identity info + organizationalUnits := []string{fmt.Sprintf("app:%s", certNames.AppGUID)} + if certNames.SpaceGUID != "" { + organizationalUnits = append(organizationalUnits, fmt.Sprintf("space:%s", certNames.SpaceGUID)) + } + if certNames.OrgGUID != "" { + organizationalUnits = append(organizationalUnits, fmt.Sprintf("organization:%s", certNames.OrgGUID)) + } + + subject := pkix.Name{ + Organization: []string{"Cloud Foundry"}, + OrganizationalUnit: organizationalUnits, + CommonName: certNames.CommonName, + } + + certTemplate := x509.Certificate{ + SerialNumber: serialNumber, + Subject: subject, + SignatureAlgorithm: x509.SHA256WithRSA, + NotBefore: time.Now(), + NotAfter: time.Now().Add(time.Hour), + BasicConstraintsValid: true, + } + + if certNames.SANs.IP != "" { + certTemplate.IPAddresses = []net.IP{net.ParseIP(certNames.SANs.IP)} + } + if certNames.SANs.DNS != "" { + certTemplate.DNSNames = []string{certNames.SANs.DNS} + } + + rootCert, err := x509.ParseCertificate(rootCADER) + Expect(err).NotTo(HaveOccurred()) + + ownKey, err := rsa.GenerateKey(rand.Reader, 2048) + Expect(err).NotTo(HaveOccurred()) + + certDER, err := x509.CreateCertificate(rand.Reader, &certTemplate, rootCert, &ownKey.PublicKey, rootPrivateKey) + Expect(err).NotTo(HaveOccurred()) + + ownKeyPEM, ownCertPEM := CreateKeyPairFromDER(certDER, ownKey) + rootKeyPEM, rootCertPEM := CreateKeyPairFromDER(rootCADER, rootPrivateKey) + + return CertChain{ + CertPEM: ownCertPEM, + PrivKeyPEM: ownKeyPEM, + CACertPEM: rootCertPEM, + CAPrivKeyPEM: rootKeyPEM, + CACert: rootCert, + CAPrivKey: rootPrivateKey, + } +} + +// CreateInstanceIdentityCertWithCA creates a certificate chain with instance identity +// information signed by the provided CA (instead of generating a new CA) +func CreateInstanceIdentityCertWithCA(certNames InstanceIdentityCertNames, ca *CertChain) CertChain { + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + Expect(err).ToNot(HaveOccurred()) + + // Build OrganizationalUnit slice with instance identity info + organizationalUnits := []string{fmt.Sprintf("app:%s", certNames.AppGUID)} + if certNames.SpaceGUID != "" { + organizationalUnits = append(organizationalUnits, fmt.Sprintf("space:%s", certNames.SpaceGUID)) + } + if certNames.OrgGUID != "" { + organizationalUnits = append(organizationalUnits, fmt.Sprintf("organization:%s", certNames.OrgGUID)) + } + + subject := pkix.Name{ + Organization: []string{"Cloud Foundry"}, + OrganizationalUnit: organizationalUnits, + CommonName: certNames.CommonName, + } + + certTemplate := x509.Certificate{ + SerialNumber: serialNumber, + Subject: subject, + SignatureAlgorithm: x509.SHA256WithRSA, + NotBefore: time.Now(), + NotAfter: time.Now().Add(time.Hour), + BasicConstraintsValid: true, + } + + if certNames.SANs.IP != "" { + certTemplate.IPAddresses = []net.IP{net.ParseIP(certNames.SANs.IP)} + } + if certNames.SANs.DNS != "" { + certTemplate.DNSNames = []string{certNames.SANs.DNS} + } + + ownKey, err := rsa.GenerateKey(rand.Reader, 2048) + Expect(err).NotTo(HaveOccurred()) + + // Sign with the provided CA + certDER, err := x509.CreateCertificate(rand.Reader, &certTemplate, ca.CACert, &ownKey.PublicKey, ca.CAPrivKey) + Expect(err).NotTo(HaveOccurred()) + + ownKeyPEM, ownCertPEM := CreateKeyPairFromDER(certDER, ownKey) + + return CertChain{ + CertPEM: ownCertPEM, + PrivKeyPEM: ownKeyPEM, + CACertPEM: ca.CACertPEM, + CAPrivKeyPEM: ca.CAPrivKeyPEM, + CACert: ca.CACert, + CAPrivKey: ca.CAPrivKey, + } +} diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/CHANGELOG.md b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/CHANGELOG.md index 87c9ebfb2..1308c8185 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/CHANGELOG.md +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/CHANGELOG.md @@ -1,23 +1,3 @@ -# 5.9.2 (April 18, 2026) - -Fix SQL Injection via placeholder confusion with dollar quoted string literals (GHSA-j88v-2chj-qfwx) - -SQL injection can occur when: - -1. The non-default simple protocol is used. -2. A dollar quoted string literal is used in the SQL query. -3. That query contains text that would be would be interpreted outside as a placeholder outside of a string literal. -4. The value of that placeholder is controllable by the attacker. - -e.g. - -```go -attackValue := `$tag$; drop table canary; --` -_, err = tx.Exec(ctx, `select $tag$ $1 $tag$, $1`, pgx.QueryExecModeSimpleProtocol, attackValue) -``` - -This is unlikely to occur outside of a contrived scenario. - # 5.9.1 (March 22, 2026) * Fix: batch result format corruption when using cached prepared statements (reported by Dirkjan Bussink) diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/batch.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/batch.go index 805cc39ef..702fcff5b 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/batch.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/batch.go @@ -8,7 +8,7 @@ import ( "github.com/jackc/pgx/v5/pgconn" ) -// QueuedQuery is a query that has been queued for execution via a [Batch]. +// QueuedQuery is a query that has been queued for execution via a Batch. type QueuedQuery struct { SQL string Arguments []any @@ -46,7 +46,7 @@ func (qq *QueuedQuery) QueryRow(fn func(row Row) error) { // // Note: for simple batch insert uses where it is not required to handle // each potential error individually, it's sufficient to not set any callbacks, -// and just handle the return value of [BatchResults.Close]. +// and just handle the return value of BatchResults.Close. func (qq *QueuedQuery) Exec(fn func(ct pgconn.CommandTag) error) { qq.Fn = func(br BatchResults) error { ct, err := br.Exec() @@ -65,13 +65,12 @@ type Batch struct { } // Queue queues a query to batch b. query can be an SQL query or the name of a prepared statement. The only pgx option -// argument that is supported is [QueryRewriter]. Queries are executed using the connection's DefaultQueryExecMode -// (see [ConnConfig.DefaultQueryExecMode]). +// argument that is supported is QueryRewriter. Queries are executed using the connection's DefaultQueryExecMode. // -// While query can contain multiple statements if the connection's DefaultQueryExecMode is [QueryExecModeSimpleProtocol], -// this should be avoided. QueuedQuery.Fn must not be set as it will only be called for the first query. That is, -// [QueuedQuery.Query], [QueuedQuery.QueryRow], and [QueuedQuery.Exec] must not be called. In addition, any error -// messages or tracing that include the current query may reference the wrong query. +// While query can contain multiple statements if the connection's DefaultQueryExecMode is QueryModeSimple, this should +// be avoided. QueuedQuery.Fn must not be set as it will only be called for the first query. That is, QueuedQuery.Query, +// QueuedQuery.QueryRow, and QueuedQuery.Exec must not be called. In addition, any error messages or tracing that +// include the current query may reference the wrong query. func (b *Batch) Queue(query string, arguments ...any) *QueuedQuery { qq := &QueuedQuery{ SQL: query, @@ -87,20 +86,20 @@ func (b *Batch) Len() int { } type BatchResults interface { - // Exec reads the results from the next query in the batch as if the query has been sent with [Conn.Exec]. Prefer + // Exec reads the results from the next query in the batch as if the query has been sent with Conn.Exec. Prefer // calling Exec on the QueuedQuery, or just calling Close. Exec() (pgconn.CommandTag, error) - // Query reads the results from the next query in the batch as if the query has been sent with [Conn.Query]. Prefer - // calling [QueuedQuery.Query]. + // Query reads the results from the next query in the batch as if the query has been sent with Conn.Query. Prefer + // calling Query on the QueuedQuery. Query() (Rows, error) - // QueryRow reads the results from the next query in the batch as if the query has been sent with [Conn.QueryRow]. - // Prefer calling [QueuedQuery.QueryRow]. + // QueryRow reads the results from the next query in the batch as if the query has been sent with Conn.QueryRow. + // Prefer calling QueryRow on the QueuedQuery. QueryRow() Row // Close closes the batch operation. All unread results are read and any callback functions registered with - // [QueuedQuery.Query], [QueuedQuery.QueryRow], or [QueuedQuery.Exec] will be called. If a callback function returns an + // QueuedQuery.Query, QueuedQuery.QueryRow, or QueuedQuery.Exec will be called. If a callback function returns an // error or the batch encounters an error subsequent callback functions will not be called. // // For simple batch inserts inside a transaction or similar queries, it's sufficient to not set any callbacks, diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/conn.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/conn.go index 4f27a5df2..67c52ac97 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/conn.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/conn.go @@ -17,8 +17,8 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -// ConnConfig contains all the options used to establish a connection. It must be created by [ParseConfig] and -// then it can be modified. A manually initialized ConnConfig will cause [ConnectConfig] to panic. +// ConnConfig contains all the options used to establish a connection. It must be created by ParseConfig and +// then it can be modified. A manually initialized ConnConfig will cause ConnectConfig to panic. type ConnConfig struct { pgconn.Config @@ -37,8 +37,8 @@ type ConnConfig struct { // DefaultQueryExecMode controls the default mode for executing queries. By default pgx uses the extended protocol // and automatically prepares and caches prepared statements. However, this may be incompatible with proxies such as - // PGBouncer. In this case it may be preferable to use [QueryExecModeExec] or [QueryExecModeSimpleProtocol]. The same - // functionality can be controlled on a per query basis by passing a [QueryExecMode] as the first query argument. + // PGBouncer. In this case it may be preferable to use QueryExecModeExec or QueryExecModeSimpleProtocol. The same + // functionality can be controlled on a per query basis by passing a QueryExecMode as the first query argument. DefaultQueryExecMode QueryExecMode createdByParseConfig bool // Used to enforce created by ParseConfig rule. @@ -131,7 +131,7 @@ var ( ) // Connect establishes a connection with a PostgreSQL server with a connection string. See -// [pgconn.Connect] for details. +// pgconn.Connect for details. func Connect(ctx context.Context, connString string) (*Conn, error) { connConfig, err := ParseConfig(connString) if err != nil { @@ -141,7 +141,7 @@ func Connect(ctx context.Context, connString string) (*Conn, error) { } // ConnectWithOptions behaves exactly like Connect with the addition of options. At the present options is only used to -// provide a [pgconn.GetSSLPasswordFunc] function. +// provide a GetSSLPassword function. func ConnectWithOptions(ctx context.Context, connString string, options ParseConfigOptions) (*Conn, error) { connConfig, err := ParseConfigWithOptions(connString, options) if err != nil { @@ -151,7 +151,7 @@ func ConnectWithOptions(ctx context.Context, connString string, options ParseCon } // ConnectConfig establishes a connection with a PostgreSQL server with a configuration struct. -// connConfig must have been created by [ParseConfig]. +// connConfig must have been created by ParseConfig. func ConnectConfig(ctx context.Context, connConfig *ConnConfig) (*Conn, error) { // In general this improves safety. In particular avoid the config.Config.OnNotification mutation from affecting other // connections with the same config. See https://github.com/jackc/pgx/issues/618. @@ -160,8 +160,8 @@ func ConnectConfig(ctx context.Context, connConfig *ConnConfig) (*Conn, error) { return connect(ctx, connConfig) } -// ParseConfigWithOptions behaves exactly as [ParseConfig] does with the addition of options. At the present options is -// only used to provide a [pgconn.GetSSLPasswordFunc] function. +// ParseConfigWithOptions behaves exactly as ParseConfig does with the addition of options. At the present options is +// only used to provide a GetSSLPassword function. func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*ConnConfig, error) { config, err := pgconn.ParseConfigWithOptions(connString, options.ParseConfigOptions) if err != nil { @@ -308,8 +308,8 @@ func (c *Conn) Close(ctx context.Context) error { } // Prepare creates a prepared statement with name and sql. sql can contain placeholders for bound parameters. These -// placeholders are referenced positionally as $1, $2, etc. name can be used instead of sql with [Conn.Query], -// [Conn.QueryRow], and [Conn.Exec] to execute the statement. It can also be used with [Batch.Queue]. +// placeholders are referenced positionally as $1, $2, etc. name can be used instead of sql with Query, QueryRow, and +// Exec to execute the statement. It can also be used with Batch.Queue. // // The underlying PostgreSQL identifier for the prepared statement will be name if name != sql or a digest of sql if // name == sql. @@ -933,7 +933,7 @@ func (c *Conn) QueryRow(ctx context.Context, sql string, args ...any) Row { } // SendBatch sends all queued queries to the server at once. All queries are run in an implicit transaction unless -// explicit transaction control statements are executed. The returned [BatchResults] must be closed before the connection +// explicit transaction control statements are executed. The returned BatchResults must be closed before the connection // is used again. // // Depending on the QueryExecMode, all queries may be prepared before any are executed. This means that creating a table @@ -1277,7 +1277,7 @@ func (c *Conn) sanitizeForSimpleQuery(sql string, args ...any) (string, error) { return sanitize.SanitizeSQL(sql, valueArgs...) } -// LoadType inspects the database for typeName and produces a [pgtype.Type] suitable for registration. typeName must be +// LoadType inspects the database for typeName and produces a pgtype.Type suitable for registration. typeName must be // the name of a type where the underlying type(s) is already understood by pgx. It is for derived types. In particular, // typeName must be one of the following: // - An array type name of a type that is already registered. e.g. "_foo" when "foo" is registered. diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/copy_from.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/copy_from.go index 038c568cf..abcd22396 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/copy_from.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/copy_from.go @@ -10,8 +10,8 @@ import ( "github.com/jackc/pgx/v5/pgconn" ) -// CopyFromRows returns a [CopyFromSource] interface over the provided rows slice -// making it usable by [Conn.CopyFrom]. +// CopyFromRows returns a CopyFromSource interface over the provided rows slice +// making it usable by *Conn.CopyFrom. func CopyFromRows(rows [][]any) CopyFromSource { return ©FromRows{rows: rows, idx: -1} } @@ -34,8 +34,8 @@ func (ctr *copyFromRows) Err() error { return nil } -// CopyFromSlice returns a [CopyFromSource] interface over a dynamic func -// making it usable by [Conn.CopyFrom]. +// CopyFromSlice returns a CopyFromSource interface over a dynamic func +// making it usable by *Conn.CopyFrom. func CopyFromSlice(length int, next func(int) ([]any, error)) CopyFromSource { return ©FromSlice{next: next, idx: -1, len: length} } @@ -64,7 +64,7 @@ func (cts *copyFromSlice) Err() error { return cts.err } -// CopyFromFunc returns a [CopyFromSource] interface that relies on nxtf for values. +// CopyFromFunc returns a CopyFromSource interface that relies on nxtf for values. // nxtf returns rows until it either signals an 'end of data' by returning row=nil and err=nil, // or it returns an error. If nxtf returns an error, the copy is aborted. func CopyFromFunc(nxtf func() (row []any, err error)) CopyFromSource { @@ -91,7 +91,7 @@ func (g *copyFromFunc) Err() error { return g.err } -// CopyFromSource is the interface used by [Conn.CopyFrom] as the source for copy data. +// CopyFromSource is the interface used by *Conn.CopyFrom as the source for copy data. type CopyFromSource interface { // Next returns true if there is another row and makes the next row data // available to Values(). When there are no more rows available or an error @@ -260,8 +260,8 @@ func (ct *copyFrom) buildCopyBuf(buf []byte, sd *pgconn.StatementDescription) (b // CopyFrom requires all values use the binary format. A pgtype.Type that supports the binary format must be registered // for the type of each column. Almost all types implemented by pgx support the binary format. // -// Even though enum types appear to be strings they still must be registered to use with [Conn.CopyFrom]. This can be done with -// [Conn.LoadType] and [pgtype.Map.RegisterType]. +// Even though enum types appear to be strings they still must be registered to use with CopyFrom. This can be done with +// Conn.LoadType and pgtype.Map.RegisterType. func (c *Conn) CopyFrom(ctx context.Context, tableName Identifier, columnNames []string, rowSrc CopyFromSource) (int64, error) { ct := ©From{ conn: c, diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/doc.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/doc.go index 225b46472..5d2ae3889 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/doc.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/doc.go @@ -1,8 +1,8 @@ // Package pgx is a PostgreSQL database driver. /* -pgx provides a native PostgreSQL driver and can act as a [database/sql/driver]. The native PostgreSQL interface is similar -to the [database/sql] interface while providing better speed and access to PostgreSQL specific features. Use -[github.com/jackc/pgx/v5/stdlib] to use pgx as a database/sql compatible driver. See that package's documentation for +pgx provides a native PostgreSQL driver and can act as a database/sql driver. The native PostgreSQL interface is similar +to the database/sql interface while providing better speed and access to PostgreSQL specific features. Use +github.com/jackc/pgx/v5/stdlib to use pgx as a database/sql compatible driver. See that package's documentation for details. Establishing a Connection @@ -19,15 +19,15 @@ string. Connection Pool [*pgx.Conn] represents a single connection to the database and is not concurrency safe. Use package -[github.com/jackc/pgx/v5/pgxpool] for a concurrency safe connection pool. +github.com/jackc/pgx/v5/pgxpool for a concurrency safe connection pool. Query Interface -pgx implements [Conn.Query] in the familiar database/sql style. However, pgx provides generic functions such as [CollectRows] and -[ForEachRow] that are a simpler and safer way of processing rows than manually calling defer [Rows.Close], [Rows.Next], -[Rows.Scan], and [Rows.Err]. +pgx implements Query in the familiar database/sql style. However, pgx provides generic functions such as CollectRows and +ForEachRow that are a simpler and safer way of processing rows than manually calling defer rows.Close(), rows.Next(), +rows.Scan, and rows.Err(). -[CollectRows] can be used collect all returned rows into a slice. +CollectRows can be used collect all returned rows into a slice. rows, _ := conn.Query(context.Background(), "select generate_series(1,$1)", 5) numbers, err := pgx.CollectRows(rows, pgx.RowTo[int32]) @@ -36,7 +36,7 @@ pgx implements [Conn.Query] in the familiar database/sql style. However, pgx pro } // numbers => [1 2 3 4 5] -[ForEachRow] can be used to execute a callback function for every row. This is often easier than iterating over rows +ForEachRow can be used to execute a callback function for every row. This is often easier than iterating over rows directly. var sum, n int32 @@ -49,7 +49,7 @@ directly. return err } -pgx also implements [Conn.QueryRow] in the same style as database/sql. +pgx also implements QueryRow in the same style as database/sql. var name string var weight int64 @@ -58,7 +58,7 @@ pgx also implements [Conn.QueryRow] in the same style as database/sql. return err } -Use [Conn.Exec] to execute a query that does not return a result set. +Use Exec to execute a query that does not return a result set. commandTag, err := conn.Exec(context.Background(), "delete from widgets where id=$1", 42) if err != nil { @@ -70,13 +70,13 @@ Use [Conn.Exec] to execute a query that does not return a result set. PostgreSQL Data Types -pgx uses the [pgtype] package to converting Go values to and from PostgreSQL values. It supports many PostgreSQL types +pgx uses the pgtype package to converting Go values to and from PostgreSQL values. It supports many PostgreSQL types directly and is customizable and extendable. User defined data types such as enums, domains, and composite types may require type registration. See that package's documentation for details. Transactions -Transactions are started by calling [Conn.Begin]. +Transactions are started by calling Begin. tx, err := conn.Begin(context.Background()) if err != nil { @@ -96,13 +96,13 @@ Transactions are started by calling [Conn.Begin]. return err } -The [Tx] returned from [Conn.Begin] also implements the [Tx.Begin] method. This can be used to implement pseudo nested transactions. +The Tx returned from Begin also implements the Begin method. This can be used to implement pseudo nested transactions. These are internally implemented with savepoints. -Use [Conn.BeginTx] to control the transaction mode. [Conn.BeginTx] also can be used to ensure a new transaction is created instead of +Use BeginTx to control the transaction mode. BeginTx also can be used to ensure a new transaction is created instead of a pseudo nested transaction. -[BeginFunc] and [BeginTxFunc] are functions that begin a transaction, execute a function, and commit or rollback the +BeginFunc and BeginTxFunc are functions that begin a transaction, execute a function, and commit or rollback the transaction depending on the return value of the function. These can be simpler and less error prone to use. err = pgx.BeginFunc(context.Background(), conn, func(tx pgx.Tx) error { @@ -115,16 +115,16 @@ transaction depending on the return value of the function. These can be simpler Prepared Statements -Prepared statements can be manually created with the [Conn.Prepare] method. However, this is rarely necessary because pgx -includes an automatic statement cache by default. Queries run through the normal [Conn.Query], [Conn.QueryRow], and [Conn.Exec] -functions are automatically prepared on first execution and the prepared statement is reused on subsequent executions. -See [ParseConfig] for information on how to customize or disable the statement cache. +Prepared statements can be manually created with the Prepare method. However, this is rarely necessary because pgx +includes an automatic statement cache by default. Queries run through the normal Query, QueryRow, and Exec functions are +automatically prepared on first execution and the prepared statement is reused on subsequent executions. See ParseConfig +for information on how to customize or disable the statement cache. Copy Protocol -Use [Conn.CopyFrom] to efficiently insert multiple rows at a time using the PostgreSQL copy protocol. [Conn.CopyFrom] accepts a -[CopyFromSource] interface. If the data is already in a [][]any use [CopyFromRows] to wrap it in a [CopyFromSource] interface. -Or implement [CopyFromSource] to avoid buffering the entire data set in memory. +Use CopyFrom to efficiently insert multiple rows at a time using the PostgreSQL copy protocol. CopyFrom accepts a +CopyFromSource interface. If the data is already in a [][]any use CopyFromRows to wrap it in a CopyFromSource interface. +Or implement CopyFromSource to avoid buffering the entire data set in memory. rows := [][]any{ {"John", "Smith", int32(36)}, @@ -138,7 +138,7 @@ Or implement [CopyFromSource] to avoid buffering the entire data set in memory. pgx.CopyFromRows(rows), ) -When you already have a typed array using [CopyFromSlice] can be more convenient. +When you already have a typed array using CopyFromSlice can be more convenient. rows := []User{ {"John", "Smith", 36}, @@ -158,7 +158,7 @@ CopyFrom can be faster than an insert with as few as 5 rows. Listen and Notify -pgx can listen to the PostgreSQL notification system with the [Conn.WaitForNotification] method. It blocks until a +pgx can listen to the PostgreSQL notification system with the `Conn.WaitForNotification` method. It blocks until a notification is received or the context is canceled. _, err := conn.Exec(context.Background(), "listen channelname") @@ -175,25 +175,20 @@ notification is received or the context is canceled. Tracing and Logging -pgx supports tracing by setting [ConnConfig.Tracer]. To combine several tracers you can use the [github.com/jackc/pgx/v5/multitracer.Tracer]. +pgx supports tracing by setting ConnConfig.Tracer. To combine several tracers you can use the multitracer.Tracer. -In addition, the [github.com/jackc/pgx/v5/tracelog] package provides the [github.com/jackc/pgx/v5/tracelog.TraceLog] type which lets a -traditional logger act as a [QueryTracer]. +In addition, the tracelog package provides the TraceLog type which lets a traditional logger act as a Tracer. -For debug tracing of the actual PostgreSQL wire protocol messages see [github.com/jackc/pgx/v5/pgproto3]. +For debug tracing of the actual PostgreSQL wire protocol messages see github.com/jackc/pgx/v5/pgproto3. Lower Level PostgreSQL Functionality -[github.com/jackc/pgx/v5/pgconn] contains a lower level PostgreSQL driver roughly at the level of libpq. [Conn] is -implemented on top of [pgconn.PgConn]. The [Conn.PgConn] method can be used to access this lower layer. +github.com/jackc/pgx/v5/pgconn contains a lower level PostgreSQL driver roughly at the level of libpq. pgx.Conn is +implemented on top of pgconn. The Conn.PgConn() method can be used to access this lower layer. PgBouncer By default pgx automatically uses prepared statements. Prepared statements are incompatible with PgBouncer. This can be -disabled by setting a different [QueryExecMode] in [ConnConfig.DefaultQueryExecMode]. +disabled by setting a different QueryExecMode in ConnConfig.DefaultQueryExecMode. */ package pgx - -import ( - _ "github.com/jackc/pgx/v5/pgconn" // Just for allowing godoc to resolve "pgconn" -) diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go index 033a4143b..b516817cb 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/internal/sanitize/sanitize.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/hex" "fmt" - "math" "slices" "strconv" "strings" @@ -203,13 +202,12 @@ func QuoteBytes(dst, buf []byte) []byte { } type sqlLexer struct { - src string - start int - pos int - nested int // multiline comment nesting level. - dollarTag string // active tag while inside a dollar-quoted string (may be empty for $$). - stateFn stateFn - parts []Part + src string + start int + pos int + nested int // multiline comment nesting level. + stateFn stateFn + parts []Part } type stateFn func(*sqlLexer) stateFn @@ -239,15 +237,6 @@ func rawState(l *sqlLexer) stateFn { l.start = l.pos return placeholderState } - // PostgreSQL dollar-quoted string: $[tag]$...$[tag]$. The $ was - // just consumed; try to match the rest of the opening tag. - // Without this, placeholders embedded inside dollar-quoted - // literals would be incorrectly substituted. - if tagLen, ok := scanDollarQuoteTag(l.src[l.pos:]); ok { - l.dollarTag = l.src[l.pos : l.pos+tagLen] - l.pos += tagLen + 1 // advance past tag and closing '$' - return dollarQuoteState - } case '-': nextRune, width := utf8.DecodeRuneInString(l.src[l.pos:]) if nextRune == '-' { @@ -330,16 +319,8 @@ func placeholderState(l *sqlLexer) stateFn { l.pos += width if '0' <= r && r <= '9' { - // Clamp rather than silently wrap on pathological input like - // "$92233720368547758070" which would otherwise overflow int and - // could land on a valid args index. Any value above MaxInt32 far - // exceeds any plausible args length, so Sanitize will correctly - // return "insufficient arguments". - if num > (math.MaxInt32-9)/10 { - num = math.MaxInt32 - } else { - num = num*10 + int(r-'0') - } + num *= 10 + num += int(r - '0') } else { l.parts = append(l.parts, num) l.pos -= width @@ -349,68 +330,6 @@ func placeholderState(l *sqlLexer) stateFn { } } -// dollarQuoteState consumes the body of a PostgreSQL dollar-quoted string -// ($[tag]$...$[tag]$). The opening tag (including its terminating '$') has -// already been consumed. -func dollarQuoteState(l *sqlLexer) stateFn { - closer := "$" + l.dollarTag + "$" - idx := strings.Index(l.src[l.pos:], closer) - if idx < 0 { - // Unterminated — mirror the behavior of other quoted-string states by - // consuming the remaining input into the current part and stopping. - if len(l.src)-l.start > 0 { - l.parts = append(l.parts, l.src[l.start:]) - l.start = len(l.src) - } - l.pos = len(l.src) - return nil - } - l.pos += idx + len(closer) - l.dollarTag = "" - return rawState -} - -// scanDollarQuoteTag checks whether src begins with an optional dollar-quoted -// string tag followed by a closing '$'. src must point just past the opening -// '$'. Returns the byte length of the tag (zero for an anonymous $$) and -// whether a valid tag was found. -// -// Tag grammar matches the PostgreSQL lexer (scan.l): -// -// dolq_start: [A-Za-z_\x80-\xff] -// dolq_cont: [A-Za-z0-9_\x80-\xff] -func scanDollarQuoteTag(src string) (int, bool) { - first := true - for i := 0; i < len(src); { - r, w := utf8.DecodeRuneInString(src[i:]) - if r == '$' { - return i, true - } - if !isDollarTagRune(r, first) { - return 0, false - } - first = false - i += w - } - return 0, false -} - -func isDollarTagRune(r rune, first bool) bool { - switch { - case r == '_': - return true - case 'a' <= r && r <= 'z': - return true - case 'A' <= r && r <= 'Z': - return true - case !first && '0' <= r && r <= '9': - return true - case r >= 0x80 && r != utf8.RuneError: - return true - } - return false -} - func escapeStringState(l *sqlLexer) stateFn { for { r, width := utf8.DecodeRuneInString(l.src[l.pos:]) diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgconn/config.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgconn/config.go index 0177d22c5..dff550953 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgconn/config.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgconn/config.go @@ -454,37 +454,23 @@ func ParseConfigWithOptions(connString string, options ParseConfigOptions) (*Con minProto, err := parseProtocolVersion(settings["min_protocol_version"]) if err != nil { - return nil, &ParseConfigError{ConnString: connString, msg: fmt.Sprintf("invalid min_protocol_version: %q", settings["min_protocol_version"]), err: err} + return nil, &ParseConfigError{ConnString: connString, msg: "invalid min_protocol_version", err: err} } maxProto, err := parseProtocolVersion(settings["max_protocol_version"]) if err != nil { - return nil, &ParseConfigError{ConnString: connString, msg: fmt.Sprintf("invalid max_protocol_version: %q", settings["max_protocol_version"]), err: err} + return nil, &ParseConfigError{ConnString: connString, msg: "invalid max_protocol_version", err: err} + } + if minProto > maxProto { + return nil, &ParseConfigError{ConnString: connString, msg: "min_protocol_version cannot be greater than max_protocol_version"} } config.MinProtocolVersion = settings["min_protocol_version"] config.MaxProtocolVersion = settings["max_protocol_version"] - if config.MinProtocolVersion == "" { config.MinProtocolVersion = "3.0" } - - // When max_protocol_version is not explicitly set, default based on - // min_protocol_version. This matches libpq behavior: if min > 3.0, - // default max to latest; otherwise default to 3.0 for compatibility - // with older servers/poolers that don't support NegotiateProtocolVersion. if config.MaxProtocolVersion == "" { - if minProto > pgproto3.ProtocolVersion30 { - config.MaxProtocolVersion = "latest" - } else { - config.MaxProtocolVersion = "3.0" - } - } - - // Only error when max_protocol_version was explicitly set and conflicts - // with min_protocol_version. When max_protocol_version is not explicitly - // set, the auto-raise logic above already ensures a valid default. - if minProto > maxProto && settings["max_protocol_version"] != "" { - return nil, &ParseConfigError{ConnString: connString, msg: "min_protocol_version cannot be greater than max_protocol_version"} + config.MaxProtocolVersion = "3.0" } switch channelBinding := settings["channel_binding"]; channelBinding { diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go index d6587cef8..ca9a48cad 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgconn/pgconn.go @@ -538,7 +538,7 @@ func (pgConn *PgConn) signalMessage() chan struct{} { } // ReceiveMessage receives one wire protocol message from the PostgreSQL server. It must only be used when the -// connection is not busy. e.g. It is an error to call [PgConn.ReceiveMessage] while reading the result of a query. The messages +// connection is not busy. e.g. It is an error to call ReceiveMessage while reading the result of a query. The messages // are still handled by the core pgconn message handling system so receiving a NotificationResponse will still trigger // the OnNotification callback. // @@ -1125,7 +1125,7 @@ func (pgConn *PgConn) WaitForNotification(ctx context.Context) error { // implicitly wrapped in a transaction unless a transaction is already in progress or SQL contains transaction control // statements. // -// Prefer [PgConn.ExecParams] unless executing arbitrary SQL that may contain multiple queries. +// Prefer ExecParams unless executing arbitrary SQL that may contain multiple queries. func (pgConn *PgConn) Exec(ctx context.Context, sql string) *MultiResultReader { if err := pgConn.lock(); err != nil { return &MultiResultReader{ @@ -1183,7 +1183,7 @@ func (pgConn *PgConn) Exec(ctx context.Context, sql string) *MultiResultReader { // resultFormats is a slice of format codes determining for each result column whether it is encoded in text or // binary format. If resultFormats is nil all results will be in text format. // -// [ResultReader] must be closed before [PgConn] can be used again. +// ResultReader must be closed before PgConn can be used again. func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [][]byte, paramOIDs []uint32, paramFormats, resultFormats []int16) *ResultReader { result := pgConn.execExtendedPrefix(ctx, paramValues) if result.closed { @@ -1209,7 +1209,7 @@ func (pgConn *PgConn) ExecParams(ctx context.Context, sql string, paramValues [] // resultFormats is a slice of format codes determining for each result column whether it is encoded in text or // binary format. If resultFormats is nil all results will be in text format. // -// [ResultReader] must be closed before [PgConn] can be used again. +// ResultReader must be closed before PgConn can be used again. func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramValues [][]byte, paramFormats, resultFormats []int16) *ResultReader { result := pgConn.execExtendedPrefix(ctx, paramValues) if result.closed { @@ -1225,20 +1225,20 @@ func (pgConn *PgConn) ExecPrepared(ctx context.Context, stmtName string, paramVa // ExecStatement enqueues the execution of a prepared statement via the PostgreSQL extended query protocol. // -// This differs from [PgConn.ExecPrepared] in that it takes a [*StatementDescription] instead of the prepared statement name. -// Because it has the [*StatementDescription] it can avoid the Describe Portal message that [PgConn.ExecPrepared] must send to get +// This differs from ExecPrepared in that it takes a *StatementDescription instead of the prepared statement name. +// Because it has the *StatementDescription it can avoid the Describe Portal message that ExecPrepared must send to get // the result column descriptions. // // paramValues are the parameter values. It must be encoded in the format given by paramFormats. // // paramFormats is a slice of format codes determining for each paramValue column whether it is encoded in text or -// binary format. If paramFormats is nil all params are text format. ExecStatement will panic if len(paramFormats) is not +// binary format. If paramFormats is nil all params are text format. ExecPrepared will panic if len(paramFormats) is not // 0, 1, or len(paramValues). // // resultFormats is a slice of format codes determining for each result column whether it is encoded in text or binary // format. If resultFormats is nil all results will be in text format. // -// [ResultReader] must be closed before [PgConn] can be used again. +// ResultReader must be closed before PgConn can be used again. func (pgConn *PgConn) ExecStatement(ctx context.Context, statementDescription *StatementDescription, paramValues [][]byte, paramFormats, resultFormats []int16) *ResultReader { result := pgConn.execExtendedPrefix(ctx, paramValues) if result.closed { diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgproto3/startup_message.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgproto3/startup_message.go index eb48f72bf..6caab3ee4 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgproto3/startup_message.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgproto3/startup_message.go @@ -13,7 +13,6 @@ import ( const ( ProtocolVersion30 = 196608 // 3.0 ProtocolVersion32 = 196610 // 3.2 - ProtocolVersionLatest = ProtocolVersion32 // Latest is 3.2 ProtocolVersionNumber = ProtocolVersion30 // Default is still 3.0 ) diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgtype/doc.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgtype/doc.go index dbcdf692f..83dfc5de5 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgtype/doc.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgtype/doc.go @@ -1,10 +1,10 @@ // Package pgtype converts between Go and PostgreSQL values. /* -The primary type is the [Map] type. It is a map of PostgreSQL types identified by OID (object ID) to a [Codec]. A [Codec] is -responsible for converting between Go and PostgreSQL values. [NewMap] creates a [Map] with all supported standard PostgreSQL -types already registered. Additional types can be registered with [Map.RegisterType]. +The primary type is the Map type. It is a map of PostgreSQL types identified by OID (object ID) to a Codec. A Codec is +responsible for converting between Go and PostgreSQL values. NewMap creates a Map with all supported standard PostgreSQL +types already registered. Additional types can be registered with Map.RegisterType. -Use [Map.Scan] and [Map.Encode] to decode PostgreSQL values to Go and encode Go values to PostgreSQL respectively. +Use Map.Scan and Map.Encode to decode PostgreSQL values to Go and encode Go values to PostgreSQL respectively. Base Type Mapping @@ -63,8 +63,8 @@ pgtype automatically marshals and unmarshals data from json and jsonb PostgreSQL Extending Existing PostgreSQL Type Support Generally, all Codecs will support interfaces that can be implemented to enable scanning and encoding. For example, -[PointCodec] can use any Go type that implements the [PointScanner] and [PointValuer] interfaces. So rather than use -[Point] an application can directly use its own point type with pgtype as long as it implements those interfaces. +PointCodec can use any Go type that implements the PointScanner and PointValuer interfaces. So rather than use +pgtype.Point and application can directly use its own point type with pgtype as long as it implements those interfaces. See example_custom_type_test.go for an example of a custom type for the PostgreSQL point type. @@ -77,10 +77,10 @@ New PostgreSQL Type Support pgtype uses the PostgreSQL OID to determine how to encode or decode a value. pgtype supports array, composite, domain, and enum types. However, any type created in PostgreSQL with CREATE TYPE will receive a new OID. This means that the OID -of each new PostgreSQL type must be registered for pgtype to handle values of that type with the correct [Codec]. +of each new PostgreSQL type must be registered for pgtype to handle values of that type with the correct Codec. -The [github.com/jackc/pgx/v5.Conn.LoadType] method can return a [*Type] for array, composite, domain, and enum types by -inspecting the database metadata. This [*Type] can then be registered with [Map.RegisterType]. +The pgx.Conn LoadType method can return a *Type for array, composite, domain, and enum types by inspecting the database +metadata. This *Type can then be registered with Map.RegisterType. For example, the following function could be called after a connection is established: @@ -106,30 +106,30 @@ For example, the following function could be called after a connection is establ A type cannot be registered unless all types it depends on are already registered. e.g. An array type cannot be registered until its element type is registered. -[ArrayCodec] implements support for arrays. If pgtype supports type T then it can easily support []T by registering an -[ArrayCodec] for the appropriate PostgreSQL OID. In addition, [Array] type can support multi-dimensional arrays. +ArrayCodec implements support for arrays. If pgtype supports type T then it can easily support []T by registering an +ArrayCodec for the appropriate PostgreSQL OID. In addition, Array[T] type can support multi-dimensional arrays. -[CompositeCodec] implements support for PostgreSQL composite types. Go structs can be scanned into if the public fields of -the struct are in the exact order and type of the PostgreSQL type or by implementing [CompositeIndexScanner] and -[CompositeIndexGetter]. +CompositeCodec implements support for PostgreSQL composite types. Go structs can be scanned into if the public fields of +the struct are in the exact order and type of the PostgreSQL type or by implementing CompositeIndexScanner and +CompositeIndexGetter. Domain types are treated as their underlying type if the underlying type and the domain type are registered. -PostgreSQL enums can usually be treated as text. However, [EnumCodec] implements support for interning strings which can +PostgreSQL enums can usually be treated as text. However, EnumCodec implements support for interning strings which can reduce memory usage. While pgtype will often still work with unregistered types it is highly recommended that all types be registered due to an improvement in performance and the elimination of certain edge cases. If an entirely new PostgreSQL type (e.g. PostGIS types) is used then the application or a library can create a new -[Codec]. Then the OID / [Codec] mapping can be registered with [Map.RegisterType]. There is no difference between a [Codec] -defined and registered by the application and a [Codec] built in to pgtype. See any of the [Codec]s in pgtype for [Codec] +Codec. Then the OID / Codec mapping can be registered with Map.RegisterType. There is no difference between a Codec +defined and registered by the application and a Codec built in to pgtype. See any of the Codecs in pgtype for Codec examples and for examples of type registration. Encoding Unknown Types pgtype works best when the OID of the PostgreSQL type is known. But in some cases such as using the simple protocol the -OID is unknown. In this case [Map.RegisterDefaultPgType] can be used to register an assumed OID for a particular Go type. +OID is unknown. In this case Map.RegisterDefaultPgType can be used to register an assumed OID for a particular Go type. Renamed Types @@ -137,18 +137,18 @@ If pgtype does not recognize a type and that type is a renamed simple type simpl as if it is the underlying type. It currently cannot automatically detect the underlying type of renamed structs (eg.g. type MyTime time.Time). -Compatibility with [database/sql] +Compatibility with database/sql -pgtype also includes support for custom types implementing the [database/sql.Scanner] and [database/sql/driver.Valuer] +pgtype also includes support for custom types implementing the database/sql.Scanner and database/sql/driver.Valuer interfaces. Encoding Typed Nils -pgtype encodes untyped and typed nils (e.g. nil and []byte(nil)) to the SQL NULL value without going through the [Codec] -system. This means that [Codec]s and other encoding logic do not have to handle nil or *T(nil). +pgtype encodes untyped and typed nils (e.g. nil and []byte(nil)) to the SQL NULL value without going through the Codec +system. This means that Codecs and other encoding logic do not have to handle nil or *T(nil). -However, [database/sql] compatibility requires Value to be called on T(nil) when T implements [database/sql/driver.Valuer]. Therefore, -[database/sql/driver.Valuer] values are only considered NULL when *T(nil) where [database/sql/driver.Valuer] is implemented on T not on *T. See +However, database/sql compatibility requires Value to be called on T(nil) when T implements driver.Valuer. Therefore, +driver.Valuer values are only considered NULL when *T(nil) where driver.Valuer is implemented on T not on *T. See https://github.com/golang/go/issues/8415 and https://github.com/golang/go/commit/0ce1d79a6a771f7449ec493b993ed2a720917870. @@ -159,38 +159,38 @@ example_child_records_test.go for an example. Overview of Scanning Implementation -The first step is to use the OID to lookup the correct [Codec]. The [Map] will call the [Codec.PlanScan] method to get a -plan for scanning into the Go value. A [Codec] will support scanning into one or more Go types. Oftentime these Go types -are interfaces rather than explicit types. For example, [PointCodec] can use any Go type that implements the [PointScanner] -and [PointValuer] interfaces. +The first step is to use the OID to lookup the correct Codec. The Map will call the Codec's PlanScan method to get a +plan for scanning into the Go value. A Codec will support scanning into one or more Go types. Oftentime these Go types +are interfaces rather than explicit types. For example, PointCodec can use any Go type that implements the PointScanner +and PointValuer interfaces. -If a Go value is not supported directly by a [Codec] then [Map] will try see if it is a [database/sql.Scanner]. If is then that -interface will be used to scan the value. Most [database/sql.Scanner]s require the input to be in the text format (e.g. UUIDs and +If a Go value is not supported directly by a Codec then Map will try see if it is a sql.Scanner. If is then that +interface will be used to scan the value. Most sql.Scanners require the input to be in the text format (e.g. UUIDs and numeric). However, pgx will typically have received the value in the binary format. In this case the binary value will be -parsed, reencoded as text, and then passed to the [database/sql.Scanner]. This may incur additional overhead for query results with +parsed, reencoded as text, and then passed to the sql.Scanner. This may incur additional overhead for query results with a large number of affected values. -If a Go value is not supported directly by a [Codec] then [Map] will try wrapping it with additional logic and try again. -For example, [Int8Codec] does not support scanning into a renamed type (e.g. type myInt64 int64). But [Map] will detect that +If a Go value is not supported directly by a Codec then Map will try wrapping it with additional logic and try again. +For example, Int8Codec does not support scanning into a renamed type (e.g. type myInt64 int64). But Map will detect that myInt64 is a renamed type and create a plan that converts the value to the underlying int64 type and then passes that to -the [Codec] (see [TryFindUnderlyingTypeScanPlan]). +the Codec (see TryFindUnderlyingTypeScanPlan). -These plan wrappers are contained in [Map.TryWrapScanPlanFuncs]. By default these contain shared logic to handle renamed +These plan wrappers are contained in Map.TryWrapScanPlanFuncs. By default these contain shared logic to handle renamed types, pointers to pointers, slices, composite types, etc. Additional plan wrappers can be added to seamlessly integrate types that do not support pgx directly. For example, the before mentioned https://github.com/jackc/pgx-shopspring-decimal package detects decimal.Decimal values, wraps them in something -implementing [NumericScanner] and passes that to the [Codec]. +implementing NumericScanner and passes that to the Codec. -[Map.Scan] and [Map.Encode] are convenience methods that wrap [Map.PlanScan] and [Map.PlanEncode]. Determining how to scan or +Map.Scan and Map.Encode are convenience methods that wrap Map.PlanScan and Map.PlanEncode. Determining how to scan or encode a particular type may be a time consuming operation. Hence the planning and execution steps of a conversion are internally separated. Reducing Compiled Binary Size -[github.com/jackc/pgx/v5.QueryExecModeExec] and [github.com/jackc/pgx/v5.QueryExecModeSimpleProtocol] require the default -PostgreSQL type to be registered for each Go type used as a query parameter. By default pgx does this for all supported -types and their array variants. If an application does not use those query execution modes or manually registers the default -PostgreSQL type for the types it uses as query parameters it can use the build tag nopgxregisterdefaulttypes. This omits -the default type registration and reduces the compiled binary size by ~2MB. +pgx.QueryExecModeExec and pgx.QueryExecModeSimpleProtocol require the default PostgreSQL type to be registered for each +Go type used as a query parameter. By default pgx does this for all supported types and their array variants. If an +application does not use those query execution modes or manually registers the default PostgreSQL type for the types it +uses as query parameters it can use the build tag nopgxregisterdefaulttypes. This omits the default type registration +and reduces the compiled binary size by ~2MB. */ package pgtype diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go index 253d80966..29721a482 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgtype/pgtype.go @@ -156,7 +156,7 @@ const ( BinaryFormatCode = 1 ) -// A Codec converts between Go and PostgreSQL values. A Codec must not be mutated after it is registered with a [Map]. +// A Codec converts between Go and PostgreSQL values. A Codec must not be mutated after it is registered with a Map. type Codec interface { // FormatSupported returns true if the format is supported. FormatSupported(int16) bool @@ -187,7 +187,7 @@ func (e *nullAssignmentError) Error() string { return fmt.Sprintf("cannot assign NULL to %T", e.dst) } -// Type represents a PostgreSQL data type. It must not be mutated after it is registered with a [Map]. +// Type represents a PostgreSQL data type. It must not be mutated after it is registered with a Map. type Type struct { Codec Codec Name string @@ -243,7 +243,6 @@ func NewMap() *Map { TryWrapDerefPointerEncodePlan, TryWrapBuiltinTypeEncodePlan, TryWrapFindUnderlyingTypeEncodePlan, - TryWrapStringerEncodePlan, TryWrapStructEncodePlan, TryWrapSliceEncodePlan, TryWrapMultiDimSliceEncodePlan, @@ -269,7 +268,7 @@ func (m *Map) RegisterTypes(types []*Type) { } } -// RegisterType registers a data type with the [Map]. t must not be mutated after it is registered. +// RegisterType registers a data type with the Map. t must not be mutated after it is registered. func (m *Map) RegisterType(t *Type) { m.oidToType[t.OID] = t m.nameToType[t.Name] = t @@ -295,7 +294,7 @@ func (m *Map) RegisterDefaultPgType(value any, name string) { } } -// TypeForOID returns the [Type] registered for the given OID. The returned [Type] must not be mutated. +// TypeForOID returns the Type registered for the given OID. The returned Type must not be mutated. func (m *Map) TypeForOID(oid uint32) (*Type, bool) { if dt, ok := m.oidToType[oid]; ok { return dt, true @@ -305,7 +304,7 @@ func (m *Map) TypeForOID(oid uint32) (*Type, bool) { return dt, ok } -// TypeForName returns the [Type] registered for the given name. The returned [Type] must not be mutated. +// TypeForName returns the Type registered for the given name. The returned Type must not be mutated. func (m *Map) TypeForName(name string) (*Type, bool) { if dt, ok := m.nameToType[name]; ok { return dt, true @@ -324,8 +323,8 @@ func (m *Map) buildReflectTypeToType() { } } -// TypeForValue finds a data type suitable for v. Use [Map.RegisterType] to register types that can encode and decode -// themselves. Use [Map.RegisterDefaultPgType] to register that can be handled by a registered data type. The returned [Type] +// TypeForValue finds a data type suitable for v. Use RegisterType to register types that can encode and decode +// themselves. Use RegisterDefaultPgType to register that can be handled by a registered data type. The returned Type // must not be mutated. func (m *Map) TypeForValue(v any) (*Type, bool) { if m.reflectTypeToType == nil { @@ -1447,24 +1446,6 @@ func TryWrapFindUnderlyingTypeEncodePlan(value any) (plan WrappedEncodePlanNextS return nil, nil, false } -// TryWrapStringerEncodePlan tries to wrap a fmt.Stringer type with a wrapper that provides TextValuer. This is -// intentionally a separate function from TryWrapBuiltinTypeEncodePlan so it can be ordered after -// TryWrapFindUnderlyingTypeEncodePlan. This ensures that named types with an underlying builtin type (e.g. type MyEnum -// int32 with a String() method) prefer encoding via the underlying type's codec (e.g. as an integer) rather than via -// Stringer. Stringer is only used as a fallback when no type-specific encoding plan succeeds. -// (https://github.com/jackc/pgx/discussions/2527) -func TryWrapStringerEncodePlan(value any) (plan WrappedEncodePlanNextSetter, nextValue any, ok bool) { - if _, ok := value.(driver.Valuer); ok { - return nil, nil, false - } - - if s, ok := value.(fmt.Stringer); ok { - return &wrapFmtStringerEncodePlan{}, fmtStringerWrapper{s}, true - } - - return nil, nil, false -} - type WrappedEncodePlanNextSetter interface { SetNext(EncodePlan) EncodePlan @@ -1525,6 +1506,8 @@ func TryWrapBuiltinTypeEncodePlan(value any) (plan WrappedEncodePlanNextSetter, return &wrapByte16EncodePlan{}, byte16Wrapper(value), true case []byte: return &wrapByteSliceEncodePlan{}, byteSliceWrapper(value), true + case fmt.Stringer: + return &wrapFmtStringerEncodePlan{}, fmtStringerWrapper{value}, true } return nil, nil, false diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go index dac8058c3..8291ed820 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/pgxpool/pool.go @@ -122,7 +122,7 @@ type ShouldPingParams struct { type Config struct { ConnConfig *pgx.ConnConfig - // BeforeConnect is called before a new connection is made. It is passed a copy of the underlying [pgx.ConnConfig] and + // BeforeConnect is called before a new connection is made. It is passed a copy of the underlying pgx.ConnConfig and // will not impact any existing open connections. BeforeConnect func(context.Context, *pgx.ConnConfig) error @@ -218,7 +218,7 @@ func New(ctx context.Context, connString string) (*Pool, error) { return NewWithConfig(ctx, config) } -// NewWithConfig creates a new [Pool]. config must have been created by [ParseConfig]. +// NewWithConfig creates a new Pool. config must have been created by [ParseConfig]. func NewWithConfig(ctx context.Context, config *Config) (*Pool, error) { // Default values are set in ParseConfig. Enforce initial creation by ParseConfig rather than setting defaults from // zero values. @@ -453,7 +453,7 @@ func ParseConfig(connString string) (*Config, error) { return config, nil } -// Close closes all connections in the pool and rejects future [Pool.Acquire] calls. Blocks until all connections are returned +// Close closes all connections in the pool and rejects future Acquire calls. Blocks until all connections are returned // to pool and closed. func (p *Pool) Close() { p.closeOnce.Do(func() { @@ -595,7 +595,7 @@ func (p *Pool) createIdleResources(parentCtx context.Context, targetResources in return firstError } -// Acquire returns a connection ([Conn]) from the [Pool]. +// Acquire returns a connection (*Conn) from the Pool func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) { if p.acquireTracer != nil { ctx = p.acquireTracer.TraceAcquireStart(ctx, p, TraceAcquireStartData{}) @@ -657,8 +657,8 @@ func (p *Pool) Acquire(ctx context.Context) (c *Conn, err error) { return nil, errors.New("pgxpool: too many failed attempts acquiring connection; likely bug in PrepareConn, BeforeAcquire, or ShouldPing hook") } -// AcquireFunc acquires a [Conn] and calls f with that [Conn]. ctx will only affect the [Pool.Acquire]. It has no effect on the -// call of f. The return value is either an error acquiring the [Conn] or the return value of f. The [Conn] is +// AcquireFunc acquires a *Conn and calls f with that *Conn. ctx will only affect the Acquire. It has no effect on the +// call of f. The return value is either an error acquiring the *Conn or the return value of f. The *Conn is // automatically released after the call of f. func (p *Pool) AcquireFunc(ctx context.Context, f func(*Conn) error) error { conn, err := p.Acquire(ctx) @@ -699,7 +699,7 @@ func (p *Pool) Reset() { p.p.Reset() } -// Config returns a copy of config that was used to initialize this [Pool]. +// Config returns a copy of config that was used to initialize this pool. func (p *Pool) Config() *Config { return p.config.Copy() } // Stat returns a pgxpool.Stat struct with a snapshot of Pool statistics. @@ -712,10 +712,10 @@ func (p *Pool) Stat() *Stat { } } -// Exec acquires a connection from the [Pool] and executes the given SQL. +// Exec acquires a connection from the Pool and executes the given SQL. // SQL can be either a prepared statement name or an SQL string. // Arguments should be referenced positionally from the SQL string as $1, $2, etc. -// The acquired connection is returned to the pool when the [Pool.Exec] function returns. +// The acquired connection is returned to the pool when the Exec function returns. func (p *Pool) Exec(ctx context.Context, sql string, arguments ...any) (pgconn.CommandTag, error) { c, err := p.Acquire(ctx) if err != nil { @@ -726,15 +726,15 @@ func (p *Pool) Exec(ctx context.Context, sql string, arguments ...any) (pgconn.C return c.Exec(ctx, sql, arguments...) } -// Query acquires a connection and executes a query that returns [pgx.Rows]. +// Query acquires a connection and executes a query that returns pgx.Rows. // Arguments should be referenced positionally from the SQL string as $1, $2, etc. -// See [pgx.Rows] documentation to close the returned [pgx.Rows] and return the acquired connection to the [Pool]. +// See pgx.Rows documentation to close the returned Rows and return the acquired connection to the Pool. // -// If there is an error, the returned [pgx.Rows] will be returned in an error state. -// If preferred, ignore the error returned from [Pool.Query] and handle errors using the returned [pgx.Rows]. +// If there is an error, the returned pgx.Rows will be returned in an error state. +// If preferred, ignore the error returned from Query and handle errors using the returned pgx.Rows. // -// For extra control over how the query is executed, the types [pgx.QueryExecMode], [pgx.QueryResultFormats], and -// [pgx.QueryResultFormatsByOID] may be used as the first args to control exactly how the query is executed. This is rarely +// For extra control over how the query is executed, the types QuerySimpleProtocol, QueryResultFormats, and +// QueryResultFormatsByOID may be used as the first args to control exactly how the query is executed. This is rarely // needed. See the documentation for those types for details. func (p *Pool) Query(ctx context.Context, sql string, args ...any) (pgx.Rows, error) { c, err := p.Acquire(ctx) @@ -752,16 +752,16 @@ func (p *Pool) Query(ctx context.Context, sql string, args ...any) (pgx.Rows, er } // QueryRow acquires a connection and executes a query that is expected -// to return at most one row ([pgx.Row]). Errors are deferred until [pgx.Row]'s -// Scan method is called. If the query selects no rows, [pgx.Row]'s Scan will -// return [pgx.ErrNoRows]. Otherwise, [pgx.Row]'s Scan scans the first selected row -// and discards the rest. The acquired connection is returned to the [Pool] when -// [pgx.Row]'s Scan method is called. +// to return at most one row (pgx.Row). Errors are deferred until pgx.Row's +// Scan method is called. If the query selects no rows, pgx.Row's Scan will +// return ErrNoRows. Otherwise, pgx.Row's Scan scans the first selected row +// and discards the rest. The acquired connection is returned to the Pool when +// pgx.Row's Scan method is called. // // Arguments should be referenced positionally from the SQL string as $1, $2, etc. // -// For extra control over how the query is executed, the types [pgx.QueryExecMode], [pgx.QueryResultFormats], and -// [pgx.QueryResultFormatsByOID] may be used as the first args to control exactly how the query is executed. This is rarely +// For extra control over how the query is executed, the types QuerySimpleProtocol, QueryResultFormats, and +// QueryResultFormatsByOID may be used as the first args to control exactly how the query is executed. This is rarely // needed. See the documentation for those types for details. func (p *Pool) QueryRow(ctx context.Context, sql string, args ...any) pgx.Row { c, err := p.Acquire(ctx) @@ -783,18 +783,18 @@ func (p *Pool) SendBatch(ctx context.Context, b *pgx.Batch) pgx.BatchResults { return &poolBatchResults{br: br, c: c} } -// Begin acquires a connection from the [Pool] and starts a transaction. Unlike [database/sql], the context only affects the begin command. i.e. there is no -// auto-rollback on context cancellation. Begin initiates a transaction block without explicitly setting a transaction mode for the block (see [Pool.BeginTx] with [pgx.TxOptions] if transaction mode is required). -// [*Tx] is returned, which implements the [pgx.Tx] interface. -// [Tx.Commit] or [Tx.Rollback] must be called on the returned transaction to finalize the transaction block. +// Begin acquires a connection from the Pool and starts a transaction. Unlike database/sql, the context only affects the begin command. i.e. there is no +// auto-rollback on context cancellation. Begin initiates a transaction block without explicitly setting a transaction mode for the block (see BeginTx with TxOptions if transaction mode is required). +// *pgxpool.Tx is returned, which implements the pgx.Tx interface. +// Commit or Rollback must be called on the returned transaction to finalize the transaction block. func (p *Pool) Begin(ctx context.Context) (pgx.Tx, error) { return p.BeginTx(ctx, pgx.TxOptions{}) } -// BeginTx acquires a connection from the [Pool] and starts a transaction with [pgx.TxOptions] determining the transaction mode. -// Unlike [database/sql], the context only affects the begin command. i.e. there is no auto-rollback on context cancellation. -// [*Tx] is returned, which implements the [pgx.Tx] interface. -// [Tx.Commit] or [Tx.Rollback] must be called on the returned transaction to finalize the transaction block. +// BeginTx acquires a connection from the Pool and starts a transaction with pgx.TxOptions determining the transaction mode. +// Unlike database/sql, the context only affects the begin command. i.e. there is no auto-rollback on context cancellation. +// *pgxpool.Tx is returned, which implements the pgx.Tx interface. +// Commit or Rollback must be called on the returned transaction to finalize the transaction block. func (p *Pool) BeginTx(ctx context.Context, txOptions pgx.TxOptions) (pgx.Tx, error) { c, err := p.Acquire(ctx) if err != nil { @@ -820,8 +820,8 @@ func (p *Pool) CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNam return c.Conn().CopyFrom(ctx, tableName, columnNames, rowSrc) } -// Ping acquires a connection from the [Pool] and executes an empty sql statement against it. -// If the sql returns without error, the database [Pool.Ping] is considered successful, otherwise, the error is returned. +// Ping acquires a connection from the Pool and executes an empty sql statement against it. +// If the sql returns without error, the database Ping is considered successful, otherwise, the error is returned. func (p *Pool) Ping(ctx context.Context) error { c, err := p.Acquire(ctx) if err != nil { diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/rows.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/rows.go index 2c5d24245..d74518de4 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/rows.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/rows.go @@ -13,12 +13,12 @@ import ( "github.com/jackc/pgx/v5/pgtype" ) -// Rows is the result set returned from [Conn.Query]. Rows must be closed before -// the [Conn] can be used again. Rows are closed by explicitly calling [Rows.Close], -// calling [Rows.Next] until it returns false, or when a fatal error occurs. +// Rows is the result set returned from *Conn.Query. Rows must be closed before +// the *Conn can be used again. Rows are closed by explicitly calling Close(), +// calling Next() until it returns false, or when a fatal error occurs. // -// Once a Rows is closed the only methods that may be called are [Rows.Close], [Rows.Err], -// and [Rows.CommandTag]. +// Once a Rows is closed the only methods that may be called are Close(), Err(), +// and CommandTag(). // // Rows is an interface instead of a struct to allow tests to mock Query. However, // adding a method to an interface is technically a breaking change. Because of this @@ -46,9 +46,9 @@ type Rows interface { // having been read or due to an error). // // Callers should check rows.Err() after rows.Next() returns false to detect whether result-set reading ended - // prematurely due to an error. See [Conn.Query] for details. + // prematurely due to an error. See Conn.Query for details. // - // For simpler error handling, consider using the higher-level pgx v5 [CollectRows()] and [ForEachRow()] helpers instead. + // For simpler error handling, consider using the higher-level pgx v5 CollectRows() and ForEachRow() helpers instead. Next() bool // Scan reads the values from the current row into dest values positionally. dest can include pointers to core types, @@ -70,7 +70,7 @@ type Rows interface { Conn() *Conn } -// Row is a convenience wrapper over [Rows] that is returned by [Conn.QueryRow]. +// Row is a convenience wrapper over Rows that is returned by QueryRow. // // Row is an interface instead of a struct to allow tests to mock QueryRow. However, // adding a method to an interface is technically a breaking change. Because of this @@ -358,7 +358,7 @@ func (e ScanArgError) Unwrap() error { return e.Err } -// ScanRow decodes raw row data into dest. It can be used to scan rows read from the lower level [pgconn] interface. +// ScanRow decodes raw row data into dest. It can be used to scan rows read from the lower level pgconn interface. // // typeMap - OID to Go type mapping. // fieldDescriptions - OID and format of values @@ -386,8 +386,8 @@ func ScanRow(typeMap *pgtype.Map, fieldDescriptions []pgconn.FieldDescription, v return nil } -// RowsFromResultReader returns a [Rows] that will read from values resultReader and decode with typeMap. It can be used -// to read from the lower level [pgconn] interface. +// RowsFromResultReader returns a Rows that will read from values resultReader and decode with typeMap. It can be used +// to read from the lower level pgconn interface. func RowsFromResultReader(typeMap *pgtype.Map, resultReader *pgconn.ResultReader) Rows { return &baseRows{ typeMap: typeMap, @@ -460,7 +460,7 @@ func CollectRows[T any](rows Rows, fn RowToFunc[T]) ([]T, error) { } // CollectOneRow calls fn for the first row in rows and returns the result. If no rows are found returns an error where errors.Is(ErrNoRows) is true. -// CollectOneRow is to [CollectRows] as [Conn.QueryRow] is to [Conn.Query]. +// CollectOneRow is to CollectRows as QueryRow is to Query. // // This function closes the rows automatically on return. func CollectOneRow[T any](rows Rows, fn RowToFunc[T]) (T, error) { diff --git a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/tx.go b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/tx.go index 3f93a6f24..571e5e00f 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/tx.go +++ b/src/code.cloudfoundry.org/vendor/github.com/jackc/pgx/v5/tx.go @@ -89,13 +89,13 @@ var ErrTxClosed = errors.New("tx is closed") // it is treated as ROLLBACK. var ErrTxCommitRollback = errors.New("commit unexpectedly resulted in rollback") -// Begin starts a transaction. Unlike [database/sql], the context only affects the begin command. i.e. there is no +// Begin starts a transaction. Unlike database/sql, the context only affects the begin command. i.e. there is no // auto-rollback on context cancellation. func (c *Conn) Begin(ctx context.Context) (Tx, error) { return c.BeginTx(ctx, TxOptions{}) } -// BeginTx starts a transaction with txOptions determining the transaction mode. Unlike [database/sql], the context only +// BeginTx starts a transaction with txOptions determining the transaction mode. Unlike database/sql, the context only // affects the begin command. i.e. there is no auto-rollback on context cancellation. func (c *Conn) BeginTx(ctx context.Context, txOptions TxOptions) (Tx, error) { _, err := c.Exec(ctx, txOptions.beginSQL()) @@ -385,8 +385,8 @@ func (sp *dbSimulatedNestedTx) Conn() *Conn { return sp.tx.Conn() } -// BeginFunc calls Begin on db and then calls fn. If fn does not return an error then it calls [Tx.Commit] on db. If fn -// returns an error it calls [Tx.Rollback] on db. The context will be used when executing the transaction control statements +// BeginFunc calls Begin on db and then calls fn. If fn does not return an error then it calls Commit on db. If fn +// returns an error it calls Rollback on db. The context will be used when executing the transaction control statements // (BEGIN, ROLLBACK, and COMMIT) but does not otherwise affect the execution of fn. func BeginFunc( ctx context.Context, @@ -404,8 +404,8 @@ func BeginFunc( return beginFuncExec(ctx, tx, fn) } -// BeginTxFunc calls BeginTx on db and then calls fn. If fn does not return an error then it calls [Tx.Commit] on db. If fn -// returns an error it calls [Tx.Rollback] on db. The context will be used when executing the transaction control statements +// BeginTxFunc calls BeginTx on db and then calls fn. If fn does not return an error then it calls Commit on db. If fn +// returns an error it calls Rollback on db. The context will be used when executing the transaction control statements // (BEGIN, ROLLBACK, and COMMIT) but does not otherwise affect the execution of fn. func BeginTxFunc( ctx context.Context, diff --git a/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/README.md b/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/README.md index 0f0f2ae5f..4c5ed2f88 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/README.md +++ b/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/README.md @@ -27,7 +27,7 @@ For such analysis and more, please see [staticcheck](https://staticcheck.dev/). go install github.com/kisielk/errcheck@latest -errcheck requires Go 1.25 or newer. +errcheck requires Go 1.22 or newer. ## Use diff --git a/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go b/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go index 05e919555..325aeec98 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go +++ b/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/errcheck/errcheck.go @@ -262,7 +262,7 @@ type visitor struct { // If the call does not include a selector (like if it is a plain "f()" function call) // then the final return value will be false. func (v *visitor) selectorAndFunc(call *ast.CallExpr) (*ast.SelectorExpr, *types.Func, bool) { - sel, ok := baseCallExpr(call.Fun).(*ast.SelectorExpr) + sel, ok := call.Fun.(*ast.SelectorExpr) if !ok { return nil, nil, false } @@ -420,15 +420,14 @@ func (v *visitor) ignoreCall(call *ast.CallExpr) bool { // Currently only supports simple expressions: // 1. f() // 2. x.y.f() - // 3. x.y[T]() or x.y[T1, T2]() var id *ast.Ident - switch exp := baseCallExpr(call.Fun).(type) { + switch exp := call.Fun.(type) { case *ast.Ident: id = exp case *ast.SelectorExpr: id = exp.Sel default: - // eg: *ast.SliceExpr + // eg: *ast.SliceExpr, *ast.IndexExpr } if id == nil { @@ -451,24 +450,6 @@ func (v *visitor) ignoreCall(call *ast.CallExpr) bool { return false } -// baseCallExpr returns the underlying function expression for a call. Type -// arguments and parentheses wrap the selector/name in additional AST nodes, so -// matching call.Fun directly would miss forms like errors.AsType[T](err). -func baseCallExpr(fun ast.Expr) ast.Expr { - for { - switch f := fun.(type) { - case *ast.IndexExpr: - fun = f.X - case *ast.IndexListExpr: - fun = f.X - case *ast.ParenExpr: - fun = f.X - default: - return fun - } - } -} - // nonVendoredPkgPath returns the unvendored version of the provided package // path (or returns the provided path if it does not represent a vendored // path). diff --git a/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/errcheck/excludes.go b/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/errcheck/excludes.go index 1ccc631f1..3e28a2fdb 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/errcheck/excludes.go +++ b/src/code.cloudfoundry.org/vendor/github.com/kisielk/errcheck/errcheck/excludes.go @@ -50,9 +50,6 @@ var DefaultExcludedSymbols = []string{ // hash "(hash.Hash).Write", - "(*crypto/sha3.SHA3).Write", - "(*crypto/sha3.SHAKE).Read", - "(*crypto/sha3.SHAKE).Write", // hash/maphash "(*hash/maphash.Hash).Write", diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/.goreleaser.yml b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/.goreleaser.yml index ff3ed854f..005fd32bd 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/.goreleaser.yml +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/.goreleaser.yml @@ -21,7 +21,7 @@ builds: env: # This is the toolchain version we use for releases. To override, set the env var, e.g.: # GORELEASER_TOOLCHAIN="go1.22.8" TARGET='linux_amd64' goreleaser build --snapshot --clean --single-target - - GOTOOLCHAIN={{ envOrDefault "GORELEASER_TOOLCHAIN" "go1.26.3" }} + - GOTOOLCHAIN={{ envOrDefault "GORELEASER_TOOLCHAIN" "go1.26.2" }} - GO111MODULE=on - CGO_ENABLED=0 goos: diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/locksordering.txt b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/locksordering.txt index c288e2ae9..3dc9ff622 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/locksordering.txt +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/locksordering.txt @@ -41,7 +41,7 @@ locking the stream lock afterward would violate locking order. stream -> clMu stream -> batchMu -> clMu - stream -> clMu -> ddMu + stream -> ddMu The "mset.batches.mu" lock protects the batching state without needing to hold the stream lock. If "clMu" is used to commit a batch, it should only be acquired while already holding the batch lock. diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/auth.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/auth.go index 96c17945d..09fad3346 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/auth.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/auth.go @@ -1283,7 +1283,7 @@ func checkClientTLSCertSubject(c *client, fn tlsMapAuthFn) bool { hasEmailAddresses := len(cert.EmailAddresses) > 0 hasSubject := len(cert.Subject.String()) > 0 hasURIs := len(cert.URIs) > 0 - if !hasSANs && !hasEmailAddresses && !hasSubject && !hasURIs { + if !hasEmailAddresses && !hasSubject && !hasURIs { c.Debugf("User required in cert, none found") return false } diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/client.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/client.go index 416eab695..162c23500 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/client.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/client.go @@ -270,7 +270,7 @@ type client struct { mpay int32 msubs int32 mcl int32 - mu sync.RWMutex + mu sync.Mutex cid uint64 start time.Time nonce []byte @@ -998,7 +998,6 @@ func (c *client) RegisterUser(user *User) { // Reset perms to nil in case client previously had them. c.perms = nil c.mperms = nil - c.darray = nil } else { c.setPermissions(user.Permissions) } @@ -1036,7 +1035,6 @@ func (c *client) RegisterNkeyUser(user *NkeyUser) error { // Reset perms to nil in case client previously had them. c.perms = nil c.mperms = nil - c.darray = nil } else { c.setPermissions(user.Permissions) } @@ -1063,8 +1061,6 @@ func (c *client) setPermissions(perms *Permissions) { return } c.perms = &permissions{} - c.mperms = nil - c.darray = nil slcache := c.srv != nil && !c.srv.getOpts().NoSublistCache // Loop over publish permissions @@ -1096,7 +1092,7 @@ func (c *client) setPermissions(perms *Permissions) { if perms.Subscribe != nil { var err error if len(perms.Subscribe.Allow) > 0 { - c.perms.sub.allow = NewSublistNoCache() + c.perms.sub.allow = NewSublist(slcache) } for _, subSubject := range perms.Subscribe.Allow { sub := &subscription{} @@ -1108,7 +1104,7 @@ func (c *client) setPermissions(perms *Permissions) { c.perms.sub.allow.Insert(sub) } if len(perms.Subscribe.Deny) > 0 { - c.perms.sub.deny = NewSublistNoCache() + c.perms.sub.deny = NewSublist(slcache) // Also hold onto this array for later. c.darray = perms.Subscribe.Deny } @@ -1205,40 +1201,38 @@ func (c *client) mergeDenyPermissions(what denyType, denyPubs []string) { if c.perms == nil { c.perms = &permissions{} } - if what == pub || what == both { - if c.perms.pub.deny == nil { - c.perms.pub.deny = NewSublistForServer(c.srv) - } - mergeDenyPerm(&c.perms.pub, denyPubs) - } - if what == sub || what == both { - if c.perms.sub.deny == nil { - // Avoid sublist cache contention in canSubscribe. - c.perms.sub.deny = NewSublistNoCache() - } - mergeDenyPerm(&c.perms.sub, denyPubs) - } -} - -// mergeDenyPerm inserts new deny permissions, skipping subjects that already exist. -func mergeDenyPerm(p *perm, denyPubs []string) { -FOR_DENY: - for _, subj := range denyPubs { - r := p.deny.Match(subj) - for _, v := range r.qsubs { - for _, s := range v { + slcache := c.srv != nil && !c.srv.getOpts().NoSublistCache + var perms []*perm + switch what { + case pub: + perms = []*perm{&c.perms.pub} + case sub: + perms = []*perm{&c.perms.sub} + case both: + perms = []*perm{&c.perms.pub, &c.perms.sub} + } + for _, p := range perms { + if p.deny == nil { + p.deny = NewSublist(slcache) + } + FOR_DENY: + for _, subj := range denyPubs { + r := p.deny.Match(subj) + for _, v := range r.qsubs { + for _, s := range v { + if string(s.subject) == subj { + continue FOR_DENY + } + } + } + for _, s := range r.psubs { if string(s.subject) == subj { continue FOR_DENY } } + sub := &subscription{subject: []byte(subj)} + p.deny.Insert(sub) } - for _, s := range r.psubs { - if string(s.subject) == subj { - continue FOR_DENY - } - } - sub := &subscription{subject: []byte(subj)} - p.deny.Insert(sub) } } @@ -1541,11 +1535,6 @@ func (c *client) readLoop(pre []byte) { acc.stats.Unlock() } - if c.kind == CLIENT { - atomic.AddInt64(&s.inClientMsgs, inMsgs) - atomic.AddInt64(&s.inClientBytes, inBytes) - } - atomic.AddInt64(&s.inMsgs, inMsgs) atomic.AddInt64(&s.inBytes, inBytes) } @@ -2695,12 +2684,6 @@ func (c *client) processPing() { srv.mu.Lock() info := srv.copyInfo() c.mu.Lock() - // Keep the in-process tls_required override from the initial INFO, - // otherwise this async INFO would flip it back to true. - if c.iproc && info.TLSRequired && !c.flags.isSet(didTLSFirst) { - info.TLSRequired = false - info.TLSAvailable = true - } info.RemoteAccount = c.acc.Name info.IsSystemAccount = c.acc == srv.SystemAccount() info.ConnectInfo = true @@ -3257,9 +3240,9 @@ func (c *client) addShadowSub(sub *subscription, ime *ime) (*subscription, error return &nsub, nil } -// canSubscribeInternal determines if the client is authorized to subscribe to -// the given subject. Assumes caller is holding at least a read lock. -func (c *client) canSubscribeInternal(subject string, optQueue ...string) bool { +// canSubscribe determines if the client is authorized to subscribe to the +// given subject. Assumes caller is holding lock. +func (c *client) canSubscribe(subject string, optQueue ...string) bool { if c.perms == nil { return true } @@ -3304,32 +3287,23 @@ func (c *client) canSubscribeInternal(subject string, optQueue ...string) bool { // If the queue appears in the deny list, then DO NOT allow. allowed = !queueMatches(queue, r.qsubs) } - } - return allowed -} -// canSubscribe determines if the client is authorized to subscribe to the -// given subject and initializes the delivery-time deny filter when needed. -// Assumes caller is holding the write lock. -func (c *client) canSubscribe(subject string, optQueue ...string) bool { - if !c.canSubscribeInternal(subject, optQueue...) { - return false - } - // We use the actual subscription to signal us to spin up the deny mperms - // and cache. We check if the subject is a wildcard that intersects any of - // the deny clauses. - // FIXME(dlc) - We could be smarter and track when these go away and remove. - if c.mperms == nil && subjectHasWildcard(subject) { - // Whip through the deny array and check if this wildcard subject can - // overlap with any denied deliveries. - for _, sub := range c.darray { - if SubjectsCollide(sub, subject) { - c.loadMsgDenyFilter() - break + // We use the actual subscription to signal us to spin up the deny mperms + // and cache. We check if the subject is a wildcard that intersects any of + // the deny clauses. + // FIXME(dlc) - We could be smarter and track when these go away and remove. + if allowed && c.mperms == nil && subjectHasWildcard(subject) { + // Whip through the deny array and check if this wildcard subject can + // overlap with any denied deliveries. + for _, sub := range c.darray { + if SubjectsCollide(sub, subject) { + c.loadMsgDenyFilter() + break + } } } } - return true + return allowed } func queueMatches(queue string, qsubs [][]*subscription) bool { @@ -4566,8 +4540,7 @@ func removeHeaderIfPrefixPresent(hdr []byte, prefix string) []byte { } index += start if index < 1 || hdr[index-1] != '\n' { - index += len(prefix) - continue + return hdr } end := bytes.Index(hdr[index+len(prefix):], []byte(_CRLF_)) @@ -5146,7 +5119,6 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, var dlvExtraSize int64 var dlvRouteMsgs int64 var dlvLeafMsgs int64 - var dlvClientMsgs int64 // We need to know if this is a MQTT producer because they send messages // without CR_LF (we otherwise remove the size of CR_LF from message size). @@ -5160,15 +5132,12 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, totalBytes := dlvMsgs*int64(len(msg)) + dlvExtraSize routeBytes := dlvRouteMsgs*int64(len(msg)) + dlvExtraSize leafBytes := dlvLeafMsgs*int64(len(msg)) + dlvExtraSize - // dlvExtraSize applies to route/leaf header overhead, not client deliveries - clientBytes := dlvClientMsgs * int64(len(msg)) // For non MQTT producers, remove the CR_LF * number of messages if !prodIsMQTT { totalBytes -= dlvMsgs * int64(LEN_CR_LF) routeBytes -= dlvRouteMsgs * int64(LEN_CR_LF) leafBytes -= dlvLeafMsgs * int64(LEN_CR_LF) - clientBytes -= dlvClientMsgs * int64(LEN_CR_LF) } if acc != nil { @@ -5189,9 +5158,6 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, if srv := c.srv; srv != nil { atomic.AddInt64(&srv.outMsgs, dlvMsgs) atomic.AddInt64(&srv.outBytes, totalBytes) - - atomic.AddInt64(&srv.outClientMsgs, dlvClientMsgs) - atomic.AddInt64(&srv.outClientBytes, clientBytes) } } @@ -5287,9 +5253,6 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, // We don't count internal deliveries, so do only when sub.icb is nil. if sub.icb == nil { dlvMsgs++ - if sub.client.kind == CLIENT { - dlvClientMsgs++ - } } didDeliver = true } @@ -5517,8 +5480,6 @@ func (c *client) processMsgResults(acc *Account, r *SublistResult, msg, deliver, dlvRouteMsgs++ case LEAF: dlvLeafMsgs++ - case CLIENT: - dlvClientMsgs++ } } // Do the rest even when message delivery was skipped. @@ -6577,20 +6538,10 @@ func (c *client) doTLSHandshake(typ string, solicit bool, url *url.URL, tlsConfi if len(subjs) > 0 { detail = fmt.Sprintf(" (%s)", strings.Join(subjs, "; ")) } - if kind == ROUTER || kind == GATEWAY { - // Always surface these as errors, as these ports shouldn't be behind a load - // balancer or regularly probed. - c.Errorf("TLS %s handshake error: %v%s", typ, err, detail) + if kind == CLIENT { + c.Errorf("TLS handshake error: %v%s", err, detail) } else { - logf := c.Errorf - if isClientProbeTLSHandshakeError(err) { - logf = c.Debugf - } - if kind == CLIENT { - logf("TLS handshake error: %v%s", err, detail) - } else { - logf("TLS %s handshake error: %v%s", typ, err, detail) - } + c.Errorf("TLS %s handshake error: %v%s", typ, err, detail) } c.closeConnection(TLSHandshakeError) @@ -6620,17 +6571,6 @@ func (c *client) doTLSHandshake(typ string, solicit bool, url *url.URL, tlsConfi return false, err } -func isClientProbeTLSHandshakeError(err error) bool { - var netErr net.Error - if errors.As(err, &netErr) && netErr.Timeout() { - return true - } - var recordHeaderErr tls.RecordHeaderError - // Conn is only set by crypto/tls when the invalid record was the peer's - // initial handshake bytes, which is the non-TLS probe/load-balancer case. - return errors.As(err, &recordHeaderErr) && recordHeaderErr.Conn != nil -} - // getRawAuthUserLock returns the raw auth user for the client. // Will acquire the client lock. func (c *client) getRawAuthUserLock() string { diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/const.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/const.go index 2bf65247a..b173aa2a7 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/const.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/const.go @@ -66,7 +66,7 @@ func init() { const ( // VERSION is the current version for the server. - VERSION = "2.14.1" + VERSION = "2.14.0" // PROTO is the currently supported protocol. // 0 was the original diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/consumer.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/consumer.go index 43263a45c..dba951741 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/consumer.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/consumer.go @@ -511,7 +511,6 @@ type consumer struct { retention RetentionPolicy monitorWg sync.WaitGroup - monitorMu sync.Mutex // Serializes monitorWg's Add against Wait to prevent a WaitGroup reuse panic. inMonitor bool // R>1 proposals @@ -1141,10 +1140,7 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri mset.mu.Unlock() return nil, NewJSConsumerWQRequiresExplicitAckError() } - if config.DeliverPolicy != DeliverAll { - mset.mu.Unlock() - return nil, NewJSConsumerWQConsumerNotDeliverAllError() - } + if mset.numLimitableConsumers() > 0 { subjects := gatherSubjectFilters(config.FilterSubject, config.FilterSubjects) if len(subjects) == 0 { @@ -1172,6 +1168,10 @@ func (mset *stream) addConsumerWithAssignment(config *ConsumerConfig, oname stri } } } + if config.DeliverPolicy != DeliverAll { + mset.mu.Unlock() + return nil, NewJSConsumerWQConsumerNotDeliverAllError() + } } // Set name, which will be durable name if set, otherwise we create one at random. @@ -1832,14 +1832,11 @@ func (o *consumer) setLeader(isLeader bool) error { stopAndClearTimer(&o.uptmr) // Make sure to clear out any re-deliver queues o.stopAndClearPtmr() - o.rdc = nil o.rdq = nil o.rdqi.Empty() o.pending = nil o.rsm = nil o.resetPendingDeliveries() - // Reset num pending, these are only authoritative on the leader. - o.npc, o.npf = 0, 0 // ok if they are nil, we protect inside unsubscribe() o.unsubscribe(o.ackSubOld) o.unsubscribe(o.ackSub) @@ -2141,7 +2138,7 @@ func (o *consumer) deleteNotActive() { cnaStart := consumerNotActiveStartInterval o.mu.Lock() - if o.mset == nil || !o.isLeader() { + if o.mset == nil { o.mu.Unlock() return } @@ -2216,8 +2213,6 @@ func (o *consumer) deleteNotActive() { s, js := o.mset.srv, o.srv.js.Load() acc, stream, name, isDirect := o.acc.Name, o.stream, o.name, o.cfg.Direct - // Capture our own view of the assignment while we still hold the lock. - ca := o.ca var qch, cqch chan struct{} if o.srv != nil { qch = o.srv.quitCh @@ -2235,6 +2230,9 @@ func (o *consumer) deleteNotActive() { "consumer": name, }) + // We will delete locally regardless. + defer o.delete() + // If we are clustered, check if we still have this consumer assigned. // If we do forward a proposal to delete ourselves to the metacontroller leader. if !isDirect && s.JetStreamIsClustered() { @@ -2243,11 +2241,8 @@ func (o *consumer) deleteNotActive() { meta RaftNode removeEntry []byte ) - nca := js.consumerAssignment(acc, stream, name) - // Only propose the delete if the meta-layer assignment still refers to - // the consumer we captured, otherwise we'd be racing a recreated - // consumer with the same name. - if cc := js.cluster; cc != nil && ca != nil && ca.sameIdentity(nca) { + ca, cc := js.consumerAssignment(acc, stream, name), js.cluster + if ca != nil && cc != nil { meta = cc.meta cca := ca.clone() cca.Reply = _EMPTY_ @@ -2256,7 +2251,7 @@ func (o *consumer) deleteNotActive() { } js.mu.RUnlock() - if ca != nil && meta != nil { + if ca != nil && cc != nil { // Check to make sure we went away. // Don't think this needs to be a monitored go routine. jitter := time.Duration(rand.Int63n(int64(cnaStart))) @@ -2279,11 +2274,10 @@ func (o *consumer) deleteNotActive() { js.mu.RUnlock() return } - nca = js.consumerAssignment(acc, stream, name) - // Make sure this is the same consumer assignment, and not a new consumer with the same name. - match := ca.sameIdentity(nca) + nca := js.consumerAssignment(acc, stream, name) js.mu.RUnlock() - if match { + // Make sure this is the same consumer assignment, and not a new consumer with the same name. + if nca != nil && reflect.DeepEqual(nca, ca) { s.Warnf("Consumer assignment for '%s > %s > %s' not cleaned up, retrying", acc, stream, name) meta.ForwardProposal(removeEntry) if interval < cnaMax { @@ -2296,10 +2290,6 @@ func (o *consumer) deleteNotActive() { return } } - } else { - // Otherwise, we can delete locally. Either a consumer that's not tracked - // by the meta layer (direct), or a standalone non-clustered server. - o.delete() } } @@ -2351,9 +2341,7 @@ func (o *consumer) hasMaxDeliveries(seq uint64) bool { // Make sure to remove from pending. if p, ok := o.pending[seq]; ok && p != nil { delete(o.pending, seq) - // Increment by one, since the delivery count hasn't been increased above. - o.updateDelivered(p.Sequence, seq, dc+1, p.Timestamp) - o.moveAckFloor(p.Sequence, seq) + o.updateDelivered(p.Sequence, seq, dc, p.Timestamp) } // Ensure redelivered state is set, if not already. if o.rdc == nil { @@ -3257,42 +3245,14 @@ func (o *consumer) ackWait(next time.Duration) time.Duration { return o.cfg.AckWait + ackWaitDelay } -func (o *consumer) removeRedeliveredBelow(seq uint64) { - if seq == 0 { - return - } - o.mu.Lock() - for sseq := range o.rdc { - if sseq < seq { - delete(o.rdc, sseq) - o.removeFromRedeliverQueue(sseq) - } - } - o.mu.Unlock() - - if o.store != nil { - o.store.RemoveRedeliveredBelow(seq) - } -} - -// checkRedelivered drops rdq entries at/below asflr or below stream's first sequence. -// But rdc is kept until the message leaves the stream: needAck relies on rdc to mark -// messages past MaxDeliver. +// Due to bug in calculation of sequences on restoring redelivered let's do quick sanity check. // Lock should be held. func (o *consumer) checkRedelivered() { - if o.mset == nil { - return - } - var ss StreamState - o.mset.store.FastState(&ss) - var shouldUpdateState bool for sseq := range o.rdc { - if sseq <= o.asflr || sseq < ss.FirstSeq { - o.removeFromRedeliverQueue(sseq) - } - if sseq < ss.FirstSeq { + if sseq <= o.asflr { delete(o.rdc, sseq) + o.removeFromRedeliverQueue(sseq) shouldUpdateState = true } } @@ -3681,7 +3641,22 @@ func (o *consumer) processAckMsgLocked(sseq, dseq, dc uint64, reply string, doSa delete(o.pending, sseq) // Use the original deliver sequence from our pending record. dseq = p.Sequence - o.moveAckFloor(dseq, sseq) + + // Only move floors if we matched an existing pending. + if len(o.pending) == 0 { + o.adflr = o.dseq - 1 + o.asflr = o.sseq - 1 + } else if dseq == o.adflr+1 { + o.adflr, o.asflr = dseq, sseq + for ss := sseq + 1; ss < o.sseq; ss++ { + if p, ok := o.pending[ss]; ok { + if p.Sequence > 0 { + o.adflr, o.asflr = p.Sequence-1, ss-1 + } + break + } + } + } } delete(o.rdc, sseq) o.removeFromRedeliverQueue(sseq) @@ -3752,25 +3727,6 @@ func (o *consumer) processAckMsgLocked(sseq, dseq, dc uint64, reply string, doSa return ackInPlace } -// Lock should be held. -func (o *consumer) moveAckFloor(dseq, sseq uint64) { - // Only move floors if we matched an existing pending. - if len(o.pending) == 0 { - o.adflr = o.dseq - 1 - o.asflr = o.sseq - 1 - } else if dseq == o.adflr+1 { - o.adflr, o.asflr = dseq, sseq - for ss := sseq + 1; ss < o.sseq; ss++ { - if p, ok := o.pending[ss]; ok { - if p.Sequence > 0 { - o.adflr, o.asflr = p.Sequence-1, ss-1 - } - break - } - } - } -} - // Determine if this is a truly filtered consumer. Modern clients will place filtered subjects // even if the stream only has a single non-wildcard subject designation. // Read lock should be held. @@ -4807,9 +4763,7 @@ func (o *consumer) getNextMsg() (*jsPubMsg, uint64, error) { // Make sure to remove from pending. if p, ok := o.pending[seq]; ok && p != nil { delete(o.pending, seq) - // The delivery count has already been incremented once. o.updateDelivered(p.Sequence, seq, dc, p.Timestamp) - o.moveAckFloor(p.Sequence, seq) } continue } @@ -5553,11 +5507,11 @@ func (o *consumer) streamNumPendingLocked() (uint64, error) { return o.streamNumPending() } -// Will force a set from the stream store of num pending on the consumer leader. +// Will force a set from the stream store of num pending. // Depends on delivery policy, for last per subject we calculate differently. // Lock should be held. func (o *consumer) streamNumPending() (uint64, error) { - if o.mset == nil || o.mset.store == nil || !o.isLeader() { + if o.mset == nil || o.mset.store == nil { o.npc, o.npf = 0, 0 return 0, nil } @@ -6298,10 +6252,7 @@ func (o *consumer) selectStartingSeqNo() error { o.asflr = o.sseq - 1 // Set our starting sequence state. // But only if we're not clustered, if clustered we propose upon becoming leader. - o.mset.cfgMu.RLock() - isR1 := o.cfg.replicas(&o.mset.cfg) == 1 - o.mset.cfgMu.RUnlock() - if o.store != nil && o.sseq > 0 && isR1 { + if o.store != nil && o.sseq > 0 && o.cfg.replicas(&o.mset.cfg) == 1 { if err := o.store.SetStarting(o.sseq - 1); err != nil { return err } @@ -6454,9 +6405,9 @@ func (o *consumer) purge(sseq uint64, slseq uint64, isWider bool) { } delete(o.pending, seq) delete(o.rdc, seq) - o.updateAcks(p.Sequence, seq, _EMPTY_) // rdq handled below. - } else if isWider && store != nil { + } + if isWider && store != nil { // Our filtered subject, which could be all, is wider than the underlying purge. // We need to check if the pending items left are still valid. var smv StoreMsg @@ -6469,7 +6420,6 @@ func (o *consumer) purge(sseq uint64, slseq uint64, isWider bool) { } delete(o.pending, seq) delete(o.rdc, seq) - o.updateAcks(p.Sequence, seq, _EMPTY_) } } } @@ -6828,10 +6778,6 @@ func (o *consumer) decStreamPending(sseq uint64, subj string) { var rdc uint64 if wasPending { rdc = o.deliveryCount(sseq) - } else if _, ok := o.rdc[sseq]; ok && o.isLeader() { - delete(o.rdc, sseq) - // Pass 0 as the delivered sequence to only remove the redelivered state. - o.updateAcks(0, sseq, _EMPTY_) } o.mu.Unlock() @@ -6932,21 +6878,14 @@ func gatherSubjectFilters(filter string, filters []string) []string { // shouldStartMonitor will return true if we should start a monitor // goroutine or will return false if one is already running. func (o *consumer) shouldStartMonitor() bool { - // monitorMu is held across the monitorWg.Add below so that it cannot race - // a concurrent monitorWg.Wait in stopMonitoring. It is taken before o.mu to - // keep a consistent lock ordering. - o.monitorMu.Lock() - defer o.monitorMu.Unlock() - o.mu.Lock() + defer o.mu.Unlock() + if o.inMonitor { - o.mu.Unlock() return false } - o.inMonitor = true - o.mu.Unlock() - o.monitorWg.Add(1) + o.inMonitor = true return true } @@ -6962,18 +6901,6 @@ func (o *consumer) clearMonitorRunning() { } } -// stopMonitoring signals any running monitor goroutine to quit and waits for -// it to fully exit. -func (o *consumer) stopMonitoring() { - // monitorMu is held across both the quit signal and the wait so that a - // concurrent shouldStartMonitor cannot slip a new monitor generation in - // between. - o.monitorMu.Lock() - defer o.monitorMu.Unlock() - o.signalMonitorQuit() - o.monitorWg.Wait() -} - // Test whether we are in the monitor routine. func (o *consumer) isMonitorRunning() bool { o.mu.RLock() diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/dirstore.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/dirstore.go index 0fae23421..6ef11bec7 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/dirstore.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/dirstore.go @@ -230,7 +230,7 @@ func (store *DirJWTStore) Pack(maxJWTs int) (string, error) { } store.Lock() err := filepath.Walk(store.directory, func(path string, info os.FileInfo, err error) error { - if info != nil && !info.IsDir() && strings.HasSuffix(path, fileExtension) { // this is a JWT + if !info.IsDir() && strings.HasSuffix(path, fileExtension) { // this is a JWT if count == maxJWTs { // won't match negative return nil } diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/events.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/events.go index 1c69d0de8..8bc9bcd51 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/events.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/events.go @@ -374,9 +374,7 @@ type ServerStats struct { ActiveAccounts int `json:"active_accounts"` NumSubs uint32 `json:"subscriptions"` Sent DataStats `json:"sent"` - SentToClients DataStats `json:"sent_to_clients"` Received DataStats `json:"received"` - ReceivedFromClients DataStats `json:"received_from_clients"` SlowConsumers int64 `json:"slow_consumers"` SlowConsumersStats *SlowConsumersStats `json:"slow_consumer_stats,omitempty"` StaleConnections int64 `json:"stale_connections,omitempty"` @@ -614,7 +612,7 @@ RESET: // Optional raw header addition. if pm.hdr != nil { - b = append(pm.hdr[:len(pm.hdr):len(pm.hdr)], b...) + b = append(pm.hdr, b...) nhdr := len(pm.hdr) nsize := len(b) - LEN_CR_LF // MQTT producers don't have CRLF, so add it back. @@ -950,12 +948,8 @@ func (s *Server) sendStatsz(subj string) { m.Stats.ActiveAccounts = int(atomic.LoadInt32(&s.activeAccounts)) m.Stats.Received.Msgs = atomic.LoadInt64(&s.inMsgs) m.Stats.Received.Bytes = atomic.LoadInt64(&s.inBytes) - m.Stats.ReceivedFromClients.Msgs = atomic.LoadInt64(&s.inClientMsgs) - m.Stats.ReceivedFromClients.Bytes = atomic.LoadInt64(&s.inClientBytes) m.Stats.Sent.Msgs = atomic.LoadInt64(&s.outMsgs) m.Stats.Sent.Bytes = atomic.LoadInt64(&s.outBytes) - m.Stats.SentToClients.Msgs = atomic.LoadInt64(&s.outClientMsgs) - m.Stats.SentToClients.Bytes = atomic.LoadInt64(&s.outClientBytes) m.Stats.SlowConsumers = atomic.LoadInt64(&s.slowConsumers) // Evaluate the slow consumer stats, but set it only if one of the value is not 0. scs := &SlowConsumersStats{ @@ -1886,10 +1880,6 @@ func (s *Server) shutdownEventing() { } s.mu.Lock() - if s.sys == nil || s.sys.resetCh == nil { - s.mu.Unlock() - return - } clearTimer(&s.sys.sweeper) clearTimer(&s.sys.stmr) rc := s.sys.resetCh diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/filestore.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/filestore.go index 626cbe6e4..c6108ad68 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/filestore.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/filestore.go @@ -1425,7 +1425,6 @@ func (mb *msgBlock) convertCipher() error { // Reset the cache since we just read everything in. mb.cache = nil - mb.ecache.Set(nil) // Generate new keys. If we error for some reason then we will put // the old keyfile back. @@ -1463,19 +1462,10 @@ func (mb *msgBlock) convertToEncrypted() error { } else if err = mb.indexCacheBuf(buf); err != nil { // This likely indicates this was already encrypted or corrupt. mb.cache = nil - mb.ecache.Set(nil) return err } // Undo cache from above for later. mb.cache = nil - mb.ecache.Set(nil) - // Regenerate mb.bek so that the keystream offset is at zero. This matches - // what encryptOrDecryptIfNeeded does on read-back, otherwise re-entering - // convertToEncrypted with a previously-used mb.bek would write ciphertext at - // the wrong stream offset and silently corrupt the block. - if mb.bek, err = genBlockEncryptionKey(mb.fs.fcfg.Cipher, mb.seed, mb.nonce); err != nil { - return err - } mb.bek.XORKeyStream(buf, buf) <-dios err = os.WriteFile(mb.mfn, buf, defaultFilePerms) @@ -2218,22 +2208,18 @@ func (fs *fileStore) recoverTTLState() error { // Done. break } - mb.mu.Lock() - msg, _, err := mb.fetchMsgNoCopyLocked(seq, &sm) + msg, _, err := mb.fetchMsgNoCopy(seq, &sm) if err != nil { - mb.finishedWithCache() - mb.mu.Unlock() fs.warn("Error loading msg seq %d for recovering TTL: %s", seq, err) continue } - if len(msg.hdr) > 0 { - if ttl, _ := getMessageTTL(msg.hdr); ttl > 0 { - expires := time.Duration(msg.ts) + (time.Second * time.Duration(ttl)) - fs.ttls.Add(seq, int64(expires)) - } + if len(msg.hdr) == 0 { + continue + } + if ttl, _ := getMessageTTL(msg.hdr); ttl > 0 { + expires := time.Duration(msg.ts) + (time.Second * time.Duration(ttl)) + fs.ttls.Add(seq, int64(expires)) } - mb.finishedWithCache() - mb.mu.Unlock() } } return nil @@ -2303,22 +2289,18 @@ func (fs *fileStore) recoverMsgSchedulingState() error { // Done. break } - mb.mu.Lock() - msg, _, err := mb.fetchMsgNoCopyLocked(seq, &sm) + msg, _, err := mb.fetchMsgNoCopy(seq, &sm) if err != nil { - mb.finishedWithCache() - mb.mu.Unlock() fs.warn("Error loading msg seq %d for recovering message schedules: %s", seq, err) continue } - if len(msg.hdr) > 0 { - if schedule, apiErr := nextMessageSchedule(msg.hdr, msg.ts); apiErr == nil && !schedule.IsZero() { - // Copy the subject, as it's stored in the scheduling maps and the backing cache could be reused in the meantime. - fs.scheduling.init(seq, copyString(msg.subj), schedule.UnixNano()) - } + if len(msg.hdr) == 0 { + continue + } + if schedule, apiErr := nextMessageSchedule(sm.hdr, sm.ts); apiErr == nil && !schedule.IsZero() { + // Copy the subject, as it's stored in the scheduling maps and the backing cache could be reused in the meantime. + fs.scheduling.init(seq, copyString(sm.subj), schedule.UnixNano()) } - mb.finishedWithCache() - mb.mu.Unlock() } } return nil @@ -2773,7 +2755,6 @@ func (fs *fileStore) GetSeqFromTime(t time.Time) uint64 { // Using a binary search, but need to be aware of interior deletes in the block. seq := lseq + 1 - mb.mu.Lock() loop: for fseq <= lseq { mid := fseq + (lseq-fseq)/2 @@ -2781,7 +2762,7 @@ loop: // Potentially skip over gaps. We keep the original middle but keep track of a // potential delete range with an offset. for { - sm, _, err := mb.fetchMsgNoCopyLocked(mid+off, &smv) + sm, _, err := mb.fetchMsgNoCopy(mid+off, &smv) if err != nil || sm == nil { off++ if mid+off <= lseq { @@ -2808,8 +2789,6 @@ loop: fseq = mid + off + 1 } } - mb.finishedWithCache() - mb.mu.Unlock() return seq } @@ -2850,11 +2829,14 @@ func (mb *msgBlock) firstMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm * // If there are no subject matches then this is effectively no-op. hseq := uint64(math.MaxUint64) var ierr error - stree.IntersectGSL(mb.fss, sl, func(subj []byte, ss *SimpleState) bool { + stree.IntersectGSL(mb.fss, sl, func(subj []byte, ss *SimpleState) { + if ierr != nil { + return + } if ss.firstNeedsUpdate || ss.lastNeedsUpdate { // mb is already loaded into the cache so should be fast-ish. if ierr = mb.recalculateForSubj(bytesToString(subj), ss); ierr != nil { - return false + return } } first := max(start, ss.First) @@ -2862,12 +2844,12 @@ func (mb *msgBlock) firstMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm * // The start cutoff is after the last sequence for this subject, // or we think we already know of a subject with an earlier msg // than our first seq for this subject. - return true + return } // Need messages loaded from here on out. if mb.cacheNotLoaded() { if ierr = mb.loadMsgsWithLock(); ierr != nil { - return false + return } didLoad = true } @@ -2881,7 +2863,7 @@ func (mb *msgBlock) firstMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm * sm = fsm hseq = ss.First } - return true + return } for seq := first; seq <= ss.Last; seq++ { // Otherwise we have a start floor that intersects where this subject @@ -2907,7 +2889,6 @@ func (mb *msgBlock) firstMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm * // If we are here we did not match, so put the llseq back. mb.llseq = llseq } - return true }) if ierr != nil { return nil, false, ierr @@ -3145,11 +3126,14 @@ func (mb *msgBlock) prevMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm *S // If there are no subject matches then this is effectively no-op. hseq := uint64(0) var ierr error - stree.IntersectGSL(mb.fss, sl, func(subj []byte, ss *SimpleState) bool { + stree.IntersectGSL(mb.fss, sl, func(subj []byte, ss *SimpleState) { + if ierr != nil { + return + } if ss.firstNeedsUpdate || ss.lastNeedsUpdate { // mb is already loaded into the cache so should be fast-ish. if ierr = mb.recalculateForSubj(bytesToString(subj), ss); ierr != nil { - return false + return } } first := min(start, ss.Last) @@ -3158,7 +3142,7 @@ func (mb *msgBlock) prevMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm *S if first < ss.First || first <= hseq { // The start cutoff is before the first sequence for this subject, // or we already know of a subject with a later-or-equal msg. - return true + return } if first == ss.Last { // If the start floor is above where this subject starts then we can @@ -3167,7 +3151,7 @@ func (mb *msgBlock) prevMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm *S sm = fsm hseq = ss.Last } - return true + return } for seq := first; seq >= ss.First; seq-- { // Otherwise we have a start floor that intersects where this subject @@ -3193,7 +3177,6 @@ func (mb *msgBlock) prevMatchingMulti(sl *gsl.SimpleSublist, start uint64, sm *S // If we are here we did not match, so put the llseq back. mb.llseq = llseq } - return true }) if ierr != nil { return nil, false, ierr @@ -3455,29 +3438,16 @@ func (fs *fileStore) checkSkipFirstBlock(filter string, wc bool, bi int) (int, e // This is used to see if we can selectively jump start blocks based on filter subjects and a starting block index. // Will return -1 and ErrStoreEOF if no matches at all or no more from where we are. func (fs *fileStore) checkSkipFirstBlockMulti(sl *gsl.SimpleSublist, bi int) (int, error) { - // Don't bother if full wildcard. - if sl.MatchesFullWildcard() { - return bi + 1, nil - } // Move through psim to gather start and stop bounds. start, stop := uint32(math.MaxUint32), uint32(0) - guard := fs.blks[bi].getIndex() + 1 - stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) bool { + stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) { if psi.fblk < start { start = psi.fblk } - if start == guard { - // One of the subjects matches the next block, so there's no point in carrying on trying to skip. - return false - } if psi.lblk > stop { stop = psi.lblk } - return true }) - if start == guard { - return bi + 1, nil - } // Nothing was found. if start == uint32(math.MaxUint32) { return -1, ErrStoreEOF @@ -4352,10 +4322,10 @@ func (fs *fileStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPer mb := fs.blks[seqStart] bi := mb.index - stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) bool { + stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) { // If the select blk start is greater than entry's last blk skip. if bi > psi.lblk { - return true + return } total++ // We will track the subjects that are an exact match to the last block. @@ -4363,7 +4333,6 @@ func (fs *fileStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPer if psi.lblk == bi { lbm[string(subj)] = true } - return true }) // Now check if we need to inspect the seqStart block. @@ -4453,11 +4422,18 @@ func (fs *fileStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPer var ierr error var havePartial bool var updateLLTS bool - stree.IntersectGSL[SimpleState](mb.fss, sl, func(bsubj []byte, ss *SimpleState) bool { + stree.IntersectGSL[SimpleState](mb.fss, sl, func(bsubj []byte, ss *SimpleState) { + if ierr != nil { + return + } subj := bytesToString(bsubj) + if havePartial { + // If we already found a partial then don't do anything else. + return + } if ss.firstNeedsUpdate || ss.lastNeedsUpdate { if ierr = mb.recalculateForSubj(subj, ss); ierr != nil { - return false + return } } if sseq <= ss.First { @@ -4465,9 +4441,7 @@ func (fs *fileStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPer } else if sseq <= ss.Last { // We matched but its a partial. havePartial = true - return false } - return true }) if ierr != nil { mb.mu.Unlock() @@ -4520,13 +4494,12 @@ func (fs *fileStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPer // If we are here it's better to calculate totals from psim and adjust downward by scanning less blocks. start := uint32(math.MaxUint32) - stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) bool { + stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) { total += psi.total // Keep track of start index for this subject. if psi.fblk < start { start = psi.fblk } - return true }) // See if we were asked for all, if so we are done. @@ -4572,9 +4545,8 @@ func (fs *fileStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPer } // Mark fss activity. mb.lsts = ats.AccessTime() - stree.IntersectGSL(mb.fss, sl, func(bsubj []byte, ss *SimpleState) bool { + stree.IntersectGSL(mb.fss, sl, func(bsubj []byte, ss *SimpleState) { adjust += ss.Msgs - return true }) } } else { @@ -5756,6 +5728,7 @@ func (fs *fileStore) removeMsgFromBlock(mb *msgBlock, seq uint64, secure, viaLim lhdr, lmsg int ttl int64 ) + // We don't use a copy as long as that's possible. When unlocking mb or erasing, we'll copy the subject. sm, err := mb.cacheLookupNoCopy(seq, &smv) if err != nil { finishedWithCache() @@ -5766,9 +5739,7 @@ func (fs *fileStore) removeMsgFromBlock(mb *msgBlock, seq uint64, secure, viaLim } return false, err } else if sm != nil { - // subj aliases mb.cache.buf; copy now because the cache may be erased or - // recycled after we drop mb.mu. The rest are scalars stashed for later use. - subj = copyString(sm.subj) + subj = sm.subj ts = sm.ts lhdr = len(sm.hdr) lmsg = len(sm.msg) @@ -5780,6 +5751,8 @@ func (fs *fileStore) removeMsgFromBlock(mb *msgBlock, seq uint64, secure, viaLim // when the last block is empty. // If not via limits and not empty (empty writes tombstone below if last) write tombstone. if !viaLimits && !isEmpty && sm != nil { + // Need to copy the subject since we unlock and re-acquire, and the cache could change. + subj = copyString(subj) mb.mu.Unlock() // Only safe way to checkLastBlock is to unlock here... lmb, err := fs.checkLastBlock(emptyRecordLen) if err != nil { @@ -5812,6 +5785,9 @@ func (fs *fileStore) removeMsgFromBlock(mb *msgBlock, seq uint64, secure, viaLim mb.mu.Unlock() return false, err } + // Need to copy the subject, as eraseMsg will overwrite the cache and we won't + // be able to access sm.subj anymore later on. + subj = copyString(subj) if err := mb.eraseMsg(seq, int(ri), int(msz), isLastBlock); err != nil { finishedWithCache() mb.mu.Unlock() @@ -6519,9 +6495,10 @@ func (mb *msgBlock) selectNextFirst() { var smv StoreMsg sm, _ := mb.cacheLookupNoCopy(seq, &smv) if sm == nil { - // Slow path, cache not loaded. - sm, _, _ = mb.fetchMsgNoCopyLocked(seq, &smv) - mb.finishedWithCache() + // Slow path, need to unlock. + mb.mu.Unlock() + sm, _, _ = mb.fetchMsgNoCopy(seq, &smv) + mb.mu.Lock() } if sm != nil { mb.first.ts = sm.ts @@ -6699,14 +6676,8 @@ func (mb *msgBlock) tryExpireCacheLocked() { } // Check for activity on the cache that would prevent us from expiring. - // Both tns and bufts come from ats.AccessTime(), which means bufts can understate - // how recent the last activity actually was by up to one tick. - if delta := tns - bufts; delta <= int64(mb.cexp)+int64(ats.TickInterval) { - td := mb.cexp - time.Duration(delta) - if td <= 0 { - td = ats.TickInterval - } - mb.resetCacheExpireTimer(td) + if tns-bufts <= int64(mb.cexp) { + mb.resetCacheExpireTimer(mb.cexp - time.Duration(tns-bufts)) if strengthened { mb.finishedWithCache() } @@ -8488,25 +8459,25 @@ checkCache: // We assume the block was selected and is correct, so we do not do range checks. // Lock should not be held. func (mb *msgBlock) fetchMsg(seq uint64, sm *StoreMsg) (*StoreMsg, bool, error) { - mb.mu.Lock() - defer mb.mu.Unlock() - defer mb.finishedWithCache() return mb.fetchMsgEx(seq, sm, true) } // Fetch a message from this block, possibly reading in and caching the messages. // We assume the block was selected and is correct, so we do not do range checks. -// We will not copy the msg data, the returned StoreMsg's subj/hdr/msg/buf are aliased -// into mb.cache.buf and are only safe to read while mb.mu is held. -func (mb *msgBlock) fetchMsgNoCopyLocked(seq uint64, sm *StoreMsg) (*StoreMsg, bool, error) { +// We will not copy the msg data. +// Lock should not be held. +func (mb *msgBlock) fetchMsgNoCopy(seq uint64, sm *StoreMsg) (*StoreMsg, bool, error) { return mb.fetchMsgEx(seq, sm, false) } // Fetch a message from this block, possibly reading in and caching the messages. // We assume the block was selected and is correct, so we do not do range checks. // We will copy the msg data based on doCopy boolean. -// Lock should be held. +// Lock should not be held. func (mb *msgBlock) fetchMsgEx(seq uint64, sm *StoreMsg, doCopy bool) (*StoreMsg, bool, error) { + mb.mu.Lock() + defer mb.mu.Unlock() + fseq, lseq := atomic.LoadUint64(&mb.first.seq), atomic.LoadUint64(&mb.last.seq) if seq < fseq || seq > lseq { return nil, false, ErrStoreMsgNotFound @@ -8528,6 +8499,7 @@ func (mb *msgBlock) fetchMsgEx(seq uint64, sm *StoreMsg, doCopy bool) (*StoreMsg return nil, false, err } } + defer mb.finishedWithCache() llseq := mb.llseq fsm, err := mb.cacheLookupEx(seq, sm, doCopy) @@ -8535,7 +8507,7 @@ func (mb *msgBlock) fetchMsgEx(seq uint64, sm *StoreMsg, doCopy bool) (*StoreMsg return nil, false, err } expireOk := (seq == lseq && llseq == seq-1) || (seq == fseq && llseq == seq+1) - return fsm, expireOk, nil + return fsm, expireOk, err } var ( @@ -8703,15 +8675,9 @@ func (fs *fileStore) sizeForSeq(seq uint64) int { } var smv StoreMsg if mb := fs.selectMsgBlock(seq); mb != nil { - mb.mu.Lock() - sm, _, _ := mb.fetchMsgNoCopyLocked(seq, &smv) - var sz int - if sm != nil { - sz = int(fileStoreMsgSize(sm.subj, sm.hdr, sm.msg)) + if sm, _, _ := mb.fetchMsgNoCopy(seq, &smv); sm != nil { + return int(fileStoreMsgSize(sm.subj, sm.hdr, sm.msg)) } - mb.finishedWithCache() - mb.mu.Unlock() - return sz } return 0 } @@ -8901,17 +8867,9 @@ func (fs *fileStore) SubjectForSeq(seq uint64) (string, error) { mb := fs.selectMsgBlock(seq) fs.mu.RUnlock() if mb != nil { - mb.mu.Lock() - sm, _, _ := mb.fetchMsgNoCopyLocked(seq, &smv) - var subj string - if sm != nil { + if sm, _, _ := mb.fetchMsgNoCopy(seq, &smv); sm != nil { // Copy the subject, as it's used elsewhere, and the backing cache could be reused in the meantime. - subj = copyString(sm.subj) - } - mb.finishedWithCache() - mb.mu.Unlock() - if sm != nil { - return subj, nil + return copyString(sm.subj), nil } } return _EMPTY_, ErrStoreMsgNotFound @@ -9070,13 +9028,12 @@ func (fs *fileStore) LoadNextMsgMulti(sl *gsl.SimpleSublist, start uint64, smp * if start <= fs.state.FirstSeq { var total uint64 blkStart := uint32(math.MaxUint32) - stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) bool { + stree.IntersectGSL(fs.psim, sl, func(subj []byte, psi *psi) { total += psi.total // Keep track of start index for this subject. if psi.fblk < blkStart { blkStart = psi.fblk } - return true }) // Nothing available. if total == 0 { @@ -10733,18 +10690,11 @@ func (fs *fileStore) Truncate(seq uint64) (rerr error) { // at the end, after we release the lock. os.Remove(filepath.Join(fs.fcfg.StoreDir, msgDir, streamStreamStateFile)) - var hasLsm bool - var lastTime int64 + var err error + var lsm *StoreMsg smb := fs.selectMsgBlock(seq) if smb != nil { - smb.mu.Lock() - lsm, _, err := smb.fetchMsgNoCopyLocked(seq, nil) - if lsm != nil { - hasLsm = true - lastTime = lsm.ts - } - smb.finishedWithCache() - smb.mu.Unlock() + lsm, _, err = smb.fetchMsgNoCopy(seq, nil) if err != nil && err != ErrStoreMsgNotFound && err != errDeletedMsg { fs.mu.Unlock() return err @@ -10752,12 +10702,13 @@ func (fs *fileStore) Truncate(seq uint64) (rerr error) { } // Reset last so new block doesn't contain truncated sequences/timestamps. - if !hasLsm { - if smb != nil { - lastTime = smb.last.ts - } else { - lastTime = fs.state.LastTime.UnixNano() - } + var lastTime int64 + if lsm != nil { + lastTime = lsm.ts + } else if smb != nil { + lastTime = smb.last.ts + } else { + lastTime = fs.state.LastTime.UnixNano() } fs.state.LastSeq = seq fs.state.LastTime = time.Unix(0, lastTime).UTC() @@ -10779,7 +10730,7 @@ func (fs *fileStore) Truncate(seq uint64) (rerr error) { // If the selected block is not found or the message was deleted, we'll need to write a tombstone // at the truncated sequence so we don't roll backward on our last sequence and timestamp. - if !hasLsm || removeSmb { + if lsm == nil || removeSmb { if err = fs.writeTombstone(seq, lastTime); err != nil { fs.mu.Unlock() return err @@ -11617,7 +11568,7 @@ func (fs *fileStore) flushStreamStateLoop(qch, done chan struct{}) { fs.warn("File system permission denied when flushing stream state, disabling JetStream: %v", err) // messages in block cache could be lost in the worst case. // In the clustered mode it is very highly unlikely as a result of replication. - fs.srv.ShutdownJetStream() + fs.srv.DisableJetStream() return } @@ -12881,31 +12832,16 @@ func (o *consumerFileStore) UpdateAcks(dseq, sseq uint64) error { return ErrNoAckPolicy } - var kick bool - defer func() { - if kick { - o.kickFlusher() - } - }() - - // We do this regardless. - if _, ok := o.state.Redelivered[sseq]; ok { - delete(o.state.Redelivered, sseq) - kick = true - } - // On restarts the old leader may get a replay from the raft logs that are old. if dseq <= o.state.AckFloor.Consumer { return nil } if len(o.state.Pending) == 0 || o.state.Pending[sseq] == nil { + delete(o.state.Redelivered, sseq) return ErrStoreMsgNotFound } - // Done with the consistency checks, we'll always kick for below updates. - kick = true - // Check for AckAll here (or AckFlowControl which functions like AckAll). if o.cfg.AckPolicy == AckAll || o.cfg.AckPolicy == AckFlowControl { sgap := sseq - o.state.AckFloor.Stream @@ -12924,6 +12860,7 @@ func (o *consumerFileStore) UpdateAcks(dseq, sseq uint64) error { delete(o.state.Redelivered, seq) } } + o.kickFlusher() return nil } @@ -12955,25 +12892,11 @@ func (o *consumerFileStore) UpdateAcks(dseq, sseq uint64) error { } } } - return nil -} + // We do these regardless. + delete(o.state.Redelivered, sseq) -func (o *consumerFileStore) RemoveRedeliveredBelow(seq uint64) { - if seq == 0 { - return - } - o.mu.Lock() - defer o.mu.Unlock() - var removed bool - for s := range o.state.Redelivered { - if s < seq { - delete(o.state.Redelivered, s) - removed = true - } - } - if removed { - o.kickFlusher() - } + o.kickFlusher() + return nil } const seqsHdrSize = 6*binary.MaxVarintLen64 + hdrLen diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream.go index f68686466..010b170b8 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream.go @@ -209,6 +209,9 @@ func (s *Server) EnableJetStream(config *JetStreamConfig) error { maxStore, maxMem = config.MaxStore, config.MaxMemory } config = s.dynJetStreamConfig(storeDir, maxStore, maxMem) + if maxMem > 0 { + config.MaxMemory = maxMem + } if domain != _EMPTY_ { config.Domain = domain } @@ -574,7 +577,7 @@ func (s *Server) restartJetStream() error { err := s.EnableJetStream(&cfg) if err != nil { s.Warnf("Can't start JetStream: %v", err) - return s.ShutdownJetStream() + return s.DisableJetStream() } s.updateJetStreamInfoStatus(true) return nil @@ -626,7 +629,7 @@ func (s *Server) handleOutOfSpace(mset *stream) { s.Errorf("JetStream out of resources, will be DISABLED") } - go s.ShutdownJetStream() + go s.DisableJetStream() adv := &JSServerOutOfSpaceAdvisory{ TypedEvent: TypedEvent{ @@ -645,23 +648,8 @@ func (s *Server) handleOutOfSpace(mset *stream) { } // DisableJetStream will turn off JetStream and signals in clustered mode -// to have the metacontroller remove us from the peer list. Persistent -// meta-raft state on disk is removed. For transient runtime errors where -// the server should rejoin its existing meta group on restart, use -// ShutdownJetStream instead. +// to have the metacontroller remove us from the peer list. func (s *Server) DisableJetStream() error { - return s.disableJetStream(true) -} - -// ShutdownJetStream is like DisableJetStream but preserves persistent -// meta-raft state on disk so the server can rejoin the existing meta -// group on restart. Use for transient runtime errors that the operator -// is expected to fix before restarting. -func (s *Server) ShutdownJetStream() error { - return s.disableJetStream(false) -} - -func (s *Server) disableJetStream(deleteState bool) error { if !s.JetStreamEnabled() { return nil } @@ -692,12 +680,7 @@ func (s *Server) disableJetStream(deleteState bool) error { s.Warnf("JetStream timeout waiting for meta leader transfer") } } - if deleteState { - meta.Delete() - } else { - meta.Stop() - meta.WaitForStop() - } + meta.Delete() } } @@ -1828,15 +1811,13 @@ func diffCheckedLimits(a, b map[string]JetStreamAccountLimits) map[string]JetStr // Lock should be held. func (jsa *jsAccount) reservedStorage(tier string) (mem, store uint64) { for _, mset := range jsa.streams { - mset.cfgMu.RLock() - storage, replicas, maxBytes := mset.cfg.Storage, mset.cfg.Replicas, mset.cfg.MaxBytes - mset.cfgMu.RUnlock() - if (tier == _EMPTY_ || tier == tierName(replicas)) && maxBytes > 0 { - switch storage { + cfg := &mset.cfg + if (tier == _EMPTY_ || tier == tierName(cfg.Replicas)) && cfg.MaxBytes > 0 { + switch cfg.Storage { case FileStorage: - store += uint64(maxBytes) + store += uint64(cfg.MaxBytes) case MemoryStorage: - mem += uint64(maxBytes) + mem += uint64(cfg.MaxBytes) } } } @@ -2351,9 +2332,9 @@ func tierName(replicas int) string { return fmt.Sprintf("R%d", replicas) } -func isSameTier(replicasA, replicasB int) bool { - a := max(1, replicasA) - b := max(1, replicasB) +func isSameTier(cfgA, cfgB *StreamConfig) bool { + a := max(1, cfgA.Replicas) + b := max(1, cfgB.Replicas) // TODO (mh) this is where we could select based off a placement tag as well "qos:tier" return a == b } @@ -2379,12 +2360,9 @@ func (jsa *jsAccount) selectLimits(replicas int) (JetStreamAccountLimits, string // Lock should be held. func (jsa *jsAccount) countStreams(tier string, cfg *StreamConfig) (streams int) { - for _, mset := range jsa.streams { - mset.cfgMu.RLock() - name, replicas := mset.cfg.Name, mset.cfg.Replicas - mset.cfgMu.RUnlock() + for _, sa := range jsa.streams { // Don't count the stream toward the limit if it already exists. - if (tier == _EMPTY_ || isSameTier(replicas, cfg.Replicas)) && name != cfg.Name { + if (tier == _EMPTY_ || isSameTier(&sa.cfg, cfg)) && sa.cfg.Name != cfg.Name { streams++ } } @@ -2448,69 +2426,53 @@ func (jsa *jsAccount) wouldExceedLimits(storeType StorageType, tierName string, // Check account limits. // Read Lock should be held -func (js *jetStream) checkAccountLimits(selected *JetStreamAccountLimits, tier string, config *StreamConfig, currentRes int64) error { - return js.checkLimits(selected, tier, config, false, currentRes, 0) +func (js *jetStream) checkAccountLimits(selected *JetStreamAccountLimits, config *StreamConfig, currentRes int64) error { + return js.checkLimits(selected, config, false, currentRes, 0) } // Check account and server limits. // Read Lock should be held -func (js *jetStream) checkAllLimits(selected *JetStreamAccountLimits, tier string, config *StreamConfig, currentRes, maxBytesOffset int64) error { - return js.checkLimits(selected, tier, config, true, currentRes, maxBytesOffset) +func (js *jetStream) checkAllLimits(selected *JetStreamAccountLimits, config *StreamConfig, currentRes, maxBytesOffset int64) error { + return js.checkLimits(selected, config, true, currentRes, maxBytesOffset) } // Check if a new proposed msg set while exceed our account limits. // Lock should be held. -func (js *jetStream) checkLimits(selected *JetStreamAccountLimits, tier string, config *StreamConfig, checkServer bool, currentRes, maxBytesOffset int64) error { +func (js *jetStream) checkLimits(selected *JetStreamAccountLimits, config *StreamConfig, checkServer bool, currentRes, maxBytesOffset int64) error { // Check MaxConsumers if config.MaxConsumers > 0 && selected.MaxConsumers > 0 && config.MaxConsumers > selected.MaxConsumers { return NewJSMaximumConsumersLimitError() } // stream limit is checked separately on stream create only! // Check storage, memory or disk. - return js.checkBytesLimits(selected, tier, config.MaxBytes, config.Replicas, config.Storage, checkServer, currentRes, maxBytesOffset) -} - -// accountReservation returns how many bytes count against the account limit -// for a stream with the given replica count. Un-tiered limits are flat, so R>1 -// is counted as Replicas*bytes; tiered limits already bake in replication. -func accountReservation(tier string, replicas int, bytes int64) int64 { - if bytes <= 0 { - return 0 - } - if tier == _EMPTY_ && replicas > 1 { - return mulSaturate(int64(replicas), bytes) - } - return bytes + return js.checkBytesLimits(selected, config.MaxBytes, config.Storage, checkServer, currentRes, maxBytesOffset) } // Check if additional bytes will exceed our account limits and optionally the server itself. // Read Lock should be held. -func (js *jetStream) checkBytesLimits(selectedLimits *JetStreamAccountLimits, tier string, addBytes int64, replicas int, storage StorageType, checkServer bool, currentRes, maxBytesOffset int64) error { +func (js *jetStream) checkBytesLimits(selectedLimits *JetStreamAccountLimits, addBytes int64, storage StorageType, checkServer bool, currentRes, maxBytesOffset int64) error { if addBytes < 0 { addBytes = 1 } - // The per-server footprint is a single replica's worth of bytes; the - // account footprint additionally accounts for replication in un-tiered setups. - serverBytes := addSaturate(addBytes, maxBytesOffset) - accountBytes := accountReservation(tier, replicas, serverBytes) + totalBytes := addSaturate(addBytes, maxBytesOffset) switch storage { case MemoryStorage: // Account limits defined. - if selectedLimits.MaxMemory >= 0 && (currentRes > selectedLimits.MaxMemory || accountBytes > selectedLimits.MaxMemory-currentRes) { + if selectedLimits.MaxMemory >= 0 && (currentRes > selectedLimits.MaxMemory || totalBytes > selectedLimits.MaxMemory-currentRes) { return NewJSMemoryResourcesExceededError() } // Check if this server can handle request. - if checkServer && (js.memReserved > js.config.MaxMemory || serverBytes > js.config.MaxMemory-js.memReserved) { + if checkServer && (js.memReserved > js.config.MaxMemory || totalBytes > js.config.MaxMemory-js.memReserved) { return NewJSMemoryResourcesExceededError() } case FileStorage: // Account limits defined. - if selectedLimits.MaxStore >= 0 && (currentRes > selectedLimits.MaxStore || accountBytes > selectedLimits.MaxStore-currentRes) { + if selectedLimits.MaxStore >= 0 && (currentRes > selectedLimits.MaxStore || totalBytes > selectedLimits.MaxStore-currentRes) { return NewJSStorageResourcesExceededError() } // Check if this server can handle request. - if checkServer && (js.storeReserved > js.config.MaxStore || serverBytes > js.config.MaxStore-js.storeReserved) { + if checkServer && (js.storeReserved > js.config.MaxStore || totalBytes > js.config.MaxStore-js.storeReserved) { return NewJSStorageResourcesExceededError() } } @@ -2720,13 +2682,13 @@ func (s *Server) dynJetStreamConfig(storeDir string, maxStore, maxMem int64) *Je jsc.SyncInterval = opts.SyncInterval jsc.SyncAlways = opts.SyncAlways - if maxStore > 0 || (opts.maxStoreSet && maxStore == 0) { + if opts.maxStoreSet && maxStore >= 0 { jsc.MaxStore = maxStore } else { jsc.MaxStore = diskAvailable(jsc.StoreDir) } - if maxMem > 0 || (opts.maxMemSet && maxMem == 0) { + if opts.maxMemSet && maxMem >= 0 { jsc.MaxMemory = maxMem } else { // Estimate to 75% of total memory if we can determine system memory. @@ -2911,7 +2873,7 @@ func (s *Server) handleWritePermissionError() { if s.JetStreamEnabled() { s.Errorf("File system permission denied while writing, disabling JetStream") - go s.ShutdownJetStream() + go s.DisableJetStream() //TODO Send respective advisory if needed, same as in handleOutOfSpace } diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_api.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_api.go index cd1ace7e1..53525a8bc 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_api.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_api.go @@ -1352,16 +1352,19 @@ func (s *Server) jsonResponse(v any) string { // Read lock must be held func (jsa *jsAccount) tieredReservation(tier string, cfg *StreamConfig) int64 { var reservation int64 - for _, mset := range jsa.streams { - mset.cfgMu.RLock() - name, storage, replicas, maxBytes := mset.cfg.Name, mset.cfg.Storage, mset.cfg.Replicas, mset.cfg.MaxBytes - mset.cfgMu.RUnlock() + for _, sa := range jsa.streams { // Don't count the stream toward the limit if it already exists. - if name == cfg.Name { + if sa.cfg.Name == cfg.Name { continue } - if (tier == _EMPTY_ || isSameTier(replicas, cfg.Replicas)) && maxBytes > 0 && storage == cfg.Storage { - reservation = addSaturate(reservation, accountReservation(tier, replicas, maxBytes)) + if (tier == _EMPTY_ || isSameTier(&sa.cfg, cfg)) && sa.cfg.MaxBytes > 0 && sa.cfg.Storage == cfg.Storage { + // If tier is empty, all storage is flat and we should adjust for replicas. + // Otherwise if tiered, storage replication already taken into consideration. + if tier == _EMPTY_ && sa.cfg.Replicas > 1 { + reservation = addSaturate(reservation, mulSaturate(int64(sa.cfg.Replicas), sa.cfg.MaxBytes)) + } else { + reservation = addSaturate(reservation, sa.cfg.MaxBytes) + } } } return reservation @@ -1696,23 +1699,19 @@ func (s *Server) jsStreamNamesRequest(sub *subscription, c *client, _ *Account, resp.Streams = resp.Streams[:JSApiNamesLimit] } } else { - // Snapshot names once to avoid repeated cfgMu RLocks during sort+append. msets := acc.filteredStreams(filter) - names := make([]string, len(msets)) - for i, mset := range msets { - names[i] = mset.getCfgName() - } - if len(names) > 1 { - slices.Sort(names) + // Since we page results order matters. + if len(msets) > 1 { + slices.SortFunc(msets, func(i, j *stream) int { return cmp.Compare(i.cfg.Name, j.cfg.Name) }) } - numStreams = len(names) + numStreams = len(msets) if offset > numStreams { offset = numStreams } - for _, name := range names[offset:] { - resp.Streams = append(resp.Streams, name) + for _, mset := range msets[offset:] { + resp.Streams = append(resp.Streams, mset.cfg.Name) if len(resp.Streams) >= JSApiNamesLimit { break } @@ -1806,31 +1805,21 @@ func (s *Server) jsStreamListRequest(sub *subscription, c *client, _ *Account, s msets = acc.filteredStreams(filter) } - // Snapshot names once and sort the parallel slice to avoid repeated cfgMu RLocks. - type msetWithName struct { - mset *stream - name string - } - named := make([]msetWithName, len(msets)) - for i, mset := range msets { - named[i] = msetWithName{mset, mset.getCfgName()} - } - slices.SortFunc(named, func(a, b msetWithName) int { return cmp.Compare(a.name, b.name) }) + slices.SortFunc(msets, func(i, j *stream) int { return cmp.Compare(i.cfg.Name, j.cfg.Name) }) - scnt := len(named) + scnt := len(msets) if offset > scnt { offset = scnt } var missingNames []string - for _, n := range named[offset:] { - mset, name := n.mset, n.name + for _, mset := range msets[offset:] { if mset.offlineReason != _EMPTY_ { if resp.Offline == nil { resp.Offline = make(map[string]string, 1) } - resp.Offline[name] = mset.offlineReason - missingNames = append(missingNames, name) + resp.Offline[mset.getCfgName()] = mset.offlineReason + missingNames = append(missingNames, mset.getCfgName()) continue } @@ -3297,15 +3286,12 @@ func (s *Server) jsMsgDeleteRequest(sub *subscription, c *client, _ *Account, su s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - mset.cfgMu.RLock() - sealed, denyDelete := mset.cfg.Sealed, mset.cfg.DenyDelete - mset.cfgMu.RUnlock() - if sealed { + if mset.cfg.Sealed { resp.Error = NewJSStreamSealedError() s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - if denyDelete { + if mset.cfg.DenyDelete { resp.Error = NewJSStreamMsgDeleteFailedError(errors.New("message delete not permitted")) s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return @@ -3733,15 +3719,12 @@ func (s *Server) jsStreamPurgeRequest(sub *subscription, c *client, _ *Account, s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - mset.cfgMu.RLock() - sealed, denyPurge := mset.cfg.Sealed, mset.cfg.DenyPurge - mset.cfgMu.RUnlock() - if sealed { + if mset.cfg.Sealed { resp.Error = NewJSStreamSealedError() s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return } - if denyPurge { + if mset.cfg.DenyPurge { resp.Error = NewJSStreamPurgeFailedError(errors.New("stream purge not permitted")) s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp)) return @@ -3779,7 +3762,7 @@ func (acc *Account) jsNonClusteredStreamLimitsCheck(cfg *StreamConfig) *ApiError return NewJSMaximumStreamsLimitError() } reserved := jsa.tieredReservation(tier, cfg) - if err := jsa.js.checkAllLimits(selectedLimits, tier, cfg, reserved, 0); err != nil { + if err := jsa.js.checkAllLimits(selectedLimits, cfg, reserved, 0); err != nil { return NewJSStreamLimitsError(err, Unless(err)) } return nil @@ -4314,8 +4297,6 @@ func (s *Server) streamSnapshot(acc *Account, mset *stream, sr *SnapshotResult, var hdr []byte chunk := make([]byte, chunkSize) - ackTimer := time.NewTimer(snapshotAckTimeout) - defer stopAndClearTimer(&ackTimer) for index := 1; ; index++ { select { case <-slots: @@ -4328,7 +4309,7 @@ func (s *Server) streamSnapshot(acc *Account, mset *stream, sr *SnapshotResult, // The snapshotting goroutine has failed for some reason. hdr = []byte(fmt.Sprintf("NATS/1.0 500 %s\r\n\r\n", err)) goto done - case <-ackTimer.C: + case <-time.After(snapshotAckTimeout): // It's taking a very long time for the receiver to send us acks, // they have probably stalled or there is high loss on the link. hdr = []byte("NATS/1.0 408 No Flow Response\r\n\r\n") @@ -4347,7 +4328,6 @@ func (s *Server) streamSnapshot(acc *Account, mset *stream, sr *SnapshotResult, hdr = []byte("NATS/1.0 204\r\n\r\n") } mset.outq.send(newJSPubMsg(reply, _EMPTY_, ackReply, nil, chunk, nil, 0)) - ackTimer.Reset(snapshotAckTimeout) } done: diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_batching.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_batching.go index 2f4419bbf..4b04241fa 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_batching.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_batching.go @@ -451,7 +451,6 @@ func (diff *batchStagedDiff) commit(mset *stream) { if c, ok := mset.inflight[subj]; ok { c.bytes += i.bytes c.ops += i.ops - c.schedule = i.schedule } else { mset.inflight[subj] = i } @@ -531,14 +530,13 @@ func checkMsgHeadersPreClusteredProposal( discard DiscardPolicy, discardNewPer bool, maxMsgSize int, maxMsgs int64, maxMsgsPer int64, maxBytes int64, ) ([]byte, []byte, uint64, *ApiError, error) { var incr *big.Int - var hasSchedule bool // Some header checks must be checked pre proposal. if len(hdr) > 0 { // Since we encode header len as u16 make sure we do not exceed. // Again this works if it goes through but better to be pre-emptive. if len(hdr) > math.MaxUint16 { - err := fmt.Errorf("JetStream header size exceeds limits for '%s > %s'", jsa.acc().Name, name) + err := fmt.Errorf("JetStream header size exceeds limits for '%s > %s'", jsa.acc().Name, mset.cfg.Name) return hdr, msg, 0, NewJSStreamHeaderExceedsMaximumError(), err } // Counter increments. @@ -812,7 +810,6 @@ func checkMsgHeadersPreClusteredProposal( } return hdr, msg, 0, apiErr, apiErr } else if !schedule.IsZero() { - hasSchedule = true if !allowMsgSchedules { apiErr := NewJSMessageSchedulesDisabledError() return hdr, msg, 0, apiErr, apiErr @@ -880,26 +877,6 @@ func checkMsgHeadersPreClusteredProposal( } else if !allowMsgSchedules { apiErr := NewJSMessageSchedulesDisabledError() return hdr, msg, 0, apiErr, apiErr - } else { - // Check that the to-be-purged subject is a schedule message. - // We still allow this message through if there exists no message for this subject, - // to remain backward-compatible. An "expected at sequence" check can still be - // performed to make this stricter. - schedSubj := bytesToString(scheduler) - var invalid bool - if i, ok := diff.inflight[schedSubj]; ok { - invalid = !i.schedule - } else if i, ok = mset.inflight[schedSubj]; ok { - invalid = !i.schedule - } else { - var smv StoreMsg - sm, _ := mset.store.LoadLastMsg(schedSubj, &smv) - invalid = sm != nil && len(sliceHeader(JSSchedulePattern, sm.hdr)) == 0 - } - if invalid { - apiErr := NewJSMessageSchedulesSchedulerInvalidError() - return hdr, msg, 0, apiErr, apiErr - } } } else if !sourced && len(sliceHeader(JSScheduler, hdr)) > 0 { // Clients may only use Nats-Scheduler alongside Nats-Schedule-Next. @@ -953,9 +930,8 @@ func checkMsgHeadersPreClusteredProposal( if i, ok = diff.inflight[subject]; ok { i.bytes += sz i.ops++ - i.schedule = hasSchedule } else { - i = &inflightSubjectRunningTotal{bytes: sz, ops: 1, schedule: hasSchedule} + i = &inflightSubjectRunningTotal{bytes: sz, ops: 1} diff.inflight[subject] = i } diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_cluster.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_cluster.go index 48e62e1f2..d406c7f1a 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_cluster.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/jetstream_cluster.go @@ -320,21 +320,6 @@ func (ca *consumerAssignment) clearResponded() { ca.responded.Store(false) } -// sameIdentity reports whether nca refers to the same logical consumer as ca. -// Only stable identity fields (Name, Stream, Group name, Created time) are -// compared; request-routing fields like Client/Reply and transient flags are -// intentionally excluded since processClusterCreateConsumer may set the -// per-object o.ca to a clone with the original requester's Client/Reply -// preserved while the meta-layer holds the newer values. -func (ca *consumerAssignment) sameIdentity(nca *consumerAssignment) bool { - return ca != nil && nca != nil && - nca.Name == ca.Name && - nca.Stream == ca.Stream && - nca.Created.Equal(ca.Created) && - nca.Group != nil && ca.Group != nil && - nca.Group.Name == ca.Group.Name -} - // clone returns a copy of ca. Field-explicit (rather than `*ca`) and // pointer-returning so the embedded atomic.Bool isn't value-copied; // responded is transferred via Load/Store. Concurrent callers may write @@ -728,14 +713,6 @@ func (js *jetStream) isStreamHealthy(acc *Account, sa *streamAssignment) error { js.mu.RUnlock() return errors.New("stream assignment or group missing") } - // Surface any persisted assignment-level error (e.g. failed create on this - // peer due to account limits) so the health check reflects the broken state - // instead of falling through to runtime-only checks. - if sa.err != nil { - err := sa.err - js.mu.RUnlock() - return fmt.Errorf("stream assignment error: %w", err) - } streamName := sa.Config.Name node := sa.Group.node js.mu.RUnlock() @@ -811,14 +788,6 @@ func (js *jetStream) isConsumerHealthy(mset *stream, consumer string, ca *consum js.mu.RUnlock() return errors.New("consumer assignment or group missing") } - // Surface any persisted assignment-level error (e.g. failed create on this - // peer) so the health check reflects the broken state instead of falling - // through to runtime-only checks. - if ca.err != nil { - err := ca.err - js.mu.RUnlock() - return fmt.Errorf("consumer assignment error: %w", err) - } created := ca.Created node := ca.Group.node js.mu.RUnlock() @@ -3643,7 +3612,7 @@ func (js *jetStream) monitorStream(mset *stream, sa *streamAssignment, sendSnaps // If we were successful lookup up our stream now. if err == nil { if mset, err = acc.lookupStream(sa.Config.Name); mset != nil { - mset.startMonitorWg() + mset.monitorWg.Add(1) defer mset.monitorWg.Done() mset.checkInMonitor() mset.setStreamAssignment(sa) @@ -3663,7 +3632,6 @@ func (js *jetStream) monitorStream(mset *stream, sa *streamAssignment, sendSnaps mset.delete() } js.mu.Lock() - s.Warnf("Stream restore failed for '%s > %s': %v", sa.Client.serviceAccount(), sa.Config.Name, err) sa.err = err if n != nil { n.Delete() @@ -3824,7 +3792,8 @@ func (mset *stream) resetClusteredState(err error) bool { // Need to do the rest in a separate Go routine. go func() { - mset.stopMonitoring() + mset.signalMonitorQuit() + mset.monitorWg.Wait() mset.resetAndWaitOnConsumers() // Stop our stream. mset.stop(shouldDelete, false) @@ -4557,10 +4526,6 @@ func (js *jetStream) processStreamLeaderChange(mset *stream, isLeader bool) { return } - // Acquire clMu before ddMu so any inflight proposals finish first, and we can - // clean up if they added new dedupe IDs. - mset.clMu.Lock() - // Clear inflight dedupe IDs, where seq=0. mset.ddMu.Lock() var removed int @@ -4583,6 +4548,7 @@ func (js *jetStream) processStreamLeaderChange(mset *stream, isLeader bool) { } mset.ddMu.Unlock() + mset.clMu.Lock() // Clear inflight if we have it. mset.inflight = nil mset.inflightTransform = nil @@ -4591,12 +4557,6 @@ func (js *jetStream) processStreamLeaderChange(mset *stream, isLeader bool) { // Clear expected per subject state. mset.expectedPerSubjectSequence = nil mset.expectedPerSubjectInProcess = nil - - // Clear clseq on every leader transition. recalculateClusteredSeq - // repopulates it on the next proposal. - if mset.clseq > 0 { - mset.clseq = 0 - } mset.clMu.Unlock() js.mu.RLock() @@ -4618,6 +4578,14 @@ func (js *jetStream) processStreamLeaderChange(mset *stream, isLeader bool) { } } + // Clear clseq on every leader transition. recalculateClusteredSeq + // repopulates it on the next proposal. + mset.clMu.Lock() + if mset.clseq > 0 { + mset.clseq = 0 + } + mset.clMu.Unlock() + // Tell stream to switch leader status. mset.setLeader(isLeader) @@ -5073,14 +5041,14 @@ func (s *Server) removeStream(mset *stream, nsa *streamAssignment) { if js, _ := s.getJetStreamCluster(); js != nil { js.mu.Lock() nsa.Group.node = nil - nsa.err = nil isShuttingDown = js.shuttingDown js.mu.Unlock() } if !isShuttingDown { // wait for monitor to be shutdown. - mset.stopMonitoring() + mset.signalMonitorQuit() + mset.monitorWg.Wait() } mset.stop(true, false) } @@ -5100,7 +5068,6 @@ func (js *jetStream) processClusterUpdateStream(acc *Account, osa, sa *streamAss storage, cfg := sa.Config.Storage, sa.Config recovering := sa.recovering hasResponded := sa.markResponded() - hadErr := sa.err != nil js.mu.RUnlock() mset, err := acc.lookupStream(cfg.Name) @@ -5110,7 +5077,8 @@ func (js *jetStream) processClusterUpdateStream(acc *Account, osa, sa *streamAss s.Warnf("JetStream cluster detected stream remapping for '%s > %s' from %q to %q", acc, cfg.Name, osa.Group.Name, sa.Group.Name) mset.removeNode() - mset.stopMonitoring() + mset.signalMonitorQuit() + mset.monitorWg.Wait() alreadyRunning, needsNode = false, true // Make sure to clear from original. js.mu.Lock() @@ -5135,7 +5103,7 @@ func (js *jetStream) processClusterUpdateStream(acc *Account, osa, sa *streamAss "stream": mset.name(), }) } - mset.startMonitorWg() + mset.monitorWg.Add(1) // Start monitoring.. started := s.startGoRoutine( func() { js.monitorStream(mset, sa, needsNode) }, @@ -5151,7 +5119,8 @@ func (js *jetStream) processClusterUpdateStream(acc *Account, osa, sa *streamAss } else if numReplicas == 1 && alreadyRunning { // We downgraded to R1. Make sure we cleanup the raft node and the stream monitor. mset.removeNode() - mset.stopMonitoring() + mset.signalMonitorQuit() + mset.monitorWg.Wait() // In case we need to shutdown the cluster specific subs, etc. mset.mu.Lock() // Stop responding to sync requests. @@ -5168,7 +5137,9 @@ func (js *jetStream) processClusterUpdateStream(acc *Account, osa, sa *streamAss mset.setStreamAssignment(sa) // Call update. - err = mset.updateWithAdvisory(cfg, !recovering, false) + if err = mset.updateWithAdvisory(cfg, !recovering, false); err != nil { + s.Warnf("JetStream cluster error updating stream %q for account %q: %v", cfg.Name, acc.Name, err) + } } // If not found we must be expanding into this node since if we are here we know we are a member. @@ -5179,7 +5150,6 @@ func (js *jetStream) processClusterUpdateStream(acc *Account, osa, sa *streamAss if err != nil { js.mu.Lock() - s.Warnf("Stream update failed for '%s > %s': %v", sa.Client.serviceAccount(), sa.Config.Name, err) sa.err = err result := &streamAssignmentResult{ Account: sa.Client.serviceAccount(), @@ -5193,10 +5163,6 @@ func (js *jetStream) processClusterUpdateStream(acc *Account, osa, sa *streamAss // Send response to the metadata leader. They will forward to the user as needed. s.sendInternalMsgLocked(streamAssignmentSubj, _EMPTY_, nil, result) return - } else if hadErr { - js.mu.Lock() - sa.err = nil - js.mu.Unlock() } isLeader := mset.IsLeader() @@ -5253,7 +5219,6 @@ func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignme storage := sa.Config.Storage restore := sa.Restore recovering := sa.recovering - hadErr := sa.err != nil js.mu.RUnlock() // Process the raft group and make sure it's running if needed. @@ -5345,7 +5310,7 @@ func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignme } } else if err == NewJSStreamNotFoundError() { // Add in the stream here. - mset, err = acc.addStreamWithAssignment(sa.Config, nil, sa, false, true) + mset, err = acc.addStreamWithAssignment(sa.Config, nil, sa, false, false) } if mset != nil { mset.setCreatedTime(created) @@ -5362,8 +5327,8 @@ func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignme return } - s.Warnf("Stream create failed for '%s > %s': %v", sa.Client.serviceAccount(), sa.Config.Name, err) if IsNatsErr(err, JSStreamStoreFailedF) { + s.Warnf("Stream create failed for '%s > %s': %v", sa.Client.serviceAccount(), sa.Config.Name, err) err = errStreamStoreFailed } js.mu.Lock() @@ -5396,10 +5361,6 @@ func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignme s.sendInternalMsgLocked(streamAssignmentSubj, _EMPTY_, nil, result) } return - } else if hadErr { - js.mu.Lock() - sa.err = nil - js.mu.Unlock() } // Re-capture node. @@ -5411,7 +5372,7 @@ func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignme if node != nil { if !alreadyRunning { if mset != nil { - mset.startMonitorWg() + mset.monitorWg.Add(1) } started := s.startGoRoutine( func() { js.monitorStream(mset, sa, false) }, @@ -5447,7 +5408,6 @@ func (js *jetStream) processClusterCreateStream(acc *Account, sa *streamAssignme mset.delete() } js.mu.Lock() - s.Warnf("Stream restore failed for '%s > %s': %v", sa.Client.serviceAccount(), sa.Config.Name, err) sa.err = err result := &streamAssignmentResult{ Account: sa.Client.serviceAccount(), @@ -5599,7 +5559,8 @@ func (js *jetStream) processClusterDeleteStream(sa *streamAssignment, isMember, n.Delete() } // wait for monitor to be shut down - mset.stopMonitoring() + mset.signalMonitorQuit() + mset.monitorWg.Wait() err = mset.stop(true, wasLeader) stopped = true } else if isMember { @@ -5821,7 +5782,8 @@ func (s *Server) removeConsumer(o *consumer, nca *consumerAssignment) { if !isShuttingDown { // wait for monitor to be shutdown. - o.stopMonitoring() + o.signalMonitorQuit() + o.monitorWg.Wait() } o.deleteWithoutAdvisory() } @@ -5928,7 +5890,8 @@ func (js *jetStream) processClusterCreateConsumer(oca, ca *consumerAssignment, s s.Warnf("JetStream cluster detected consumer remapping for '%s > %s' from %q to %q", acc, ca.Name, oca.Group.Name, ca.Group.Name) o.clearNode() - o.stopMonitoring() + o.signalMonitorQuit() + o.monitorWg.Wait() alreadyRunning = false // Make sure to clear from original. js.mu.Lock() @@ -6036,12 +5999,13 @@ func (js *jetStream) processClusterCreateConsumer(oca, ca *consumerAssignment, s return } - s.Warnf("Consumer create failed for '%s > %s > %s': %v", ca.Client.serviceAccount(), ca.Stream, ca.Name, err) if IsNatsErr(err, JSConsumerStoreFailedErrF) { + s.Warnf("Consumer create failed for '%s > %s > %s': %v", ca.Client.serviceAccount(), ca.Stream, ca.Name, err) err = errConsumerStoreFailed } js.mu.Lock() + ca.err = err hasResponded := ca.hasResponded() @@ -6084,14 +6048,8 @@ func (js *jetStream) processClusterCreateConsumer(oca, ca *consumerAssignment, s } } else { js.mu.RLock() - hadErr := ca.err != nil node := rg.node js.mu.RUnlock() - if hadErr { - js.mu.Lock() - ca.err = nil - js.mu.Unlock() - } if didCreate { o.setCreatedTime(ca.Created) @@ -6099,7 +6057,8 @@ func (js *jetStream) processClusterCreateConsumer(oca, ca *consumerAssignment, s // Check for scale down to 1.. if node != nil && len(rg.Peers) == 1 { o.clearNode() - o.stopMonitoring() + o.signalMonitorQuit() + o.monitorWg.Wait() // Need to clear from rg too. js.mu.Lock() rg.node = nil @@ -6138,7 +6097,8 @@ func (js *jetStream) processClusterCreateConsumer(oca, ca *consumerAssignment, s if node == nil { // Wait for the previous routine to stop running. - o.stopMonitoring() + o.signalMonitorQuit() + o.monitorWg.Wait() // Single replica consumer, process manually here. // Force response in case we think this is an update. if !js.isMetaRecovering() && isConfigUpdate { @@ -6169,7 +6129,8 @@ func (js *jetStream) processClusterCreateConsumer(oca, ca *consumerAssignment, s // Start our monitoring routine if needed. if !alreadyRunning { // Wait for the previous routine to stop running. - o.stopMonitoring() + o.signalMonitorQuit() + o.monitorWg.Wait() if o.shouldStartMonitor() { started := s.startGoRoutine( func() { js.monitorConsumer(o, ca) }, @@ -7238,17 +7199,9 @@ func (js *jetStream) processStreamAssignmentResults(sub *subscription, c *client } // Remove this assignment if possible. if canDelete { - var apiErr *ApiError - if result.Response != nil { - apiErr = result.Response.Error - } else if result.Restore != nil { - apiErr = result.Restore.Error - } - s.Warnf("Stream assignment for '%s > %s' rejected by assigned member: %v", sa.Client.serviceAccount(), sa.Config.Name, apiErr) sa.err = NewJSClusterNotAssignedError() - if err := cc.meta.Propose(encodeDeleteStreamAssignment(sa)); err == nil { - cc.trackInflightStreamProposal(result.Account, sa, true) - } + cc.meta.Propose(encodeDeleteStreamAssignment(sa)) + cc.trackInflightStreamProposal(result.Account, sa, true) } } } @@ -7283,7 +7236,6 @@ func (js *jetStream) processConsumerAssignmentResults(sub *subscription, c *clie // Make sure this is recent response. if result.Response.Error != nil && result.Response.Error != NewJSConsumerNameExistError() && time.Since(ca.Created) < 2*time.Second { // Do not list in consumer names/lists. - s.Warnf("Consumer assignment for '%s > %s > %s' rejected by assigned member: %v", ca.Client.serviceAccount(), ca.Stream, ca.Name, result.Response.Error) ca.err = NewJSClusterNotAssignedError() } } @@ -7914,10 +7866,16 @@ func (js *jetStream) tieredStreamAndReservationCount(accName, tier string, cfg * if sa.Config.Name == cfg.Name { continue } - if tier == _EMPTY_ || isSameTier(sa.Config.Replicas, cfg.Replicas) { + if tier == _EMPTY_ || isSameTier(sa.Config, cfg) { numStreams++ if sa.Config.MaxBytes > 0 && sa.Config.Storage == cfg.Storage { - reservation = addSaturate(reservation, accountReservation(tier, sa.Config.Replicas, sa.Config.MaxBytes)) + // If tier is empty, all storage is flat and we should adjust for replicas. + // Otherwise if tiered, storage replication already taken into consideration. + if tier == _EMPTY_ && sa.Config.Replicas > 1 { + reservation = addSaturate(reservation, mulSaturate(int64(sa.Config.Replicas), sa.Config.MaxBytes)) + } else { + reservation = addSaturate(reservation, sa.Config.MaxBytes) + } } } } @@ -7993,7 +7951,7 @@ func (js *jetStream) jsClusteredStreamLimitsCheck(acc *Account, cfg *StreamConfi return NewJSMaximumStreamsLimitError() } // Check for account limits here before proposing. - if err := js.checkAccountLimits(selectedLimits, tier, cfg, reservations); err != nil { + if err := js.checkAccountLimits(selectedLimits, cfg, reservations); err != nil { return NewJSStreamLimitsError(err, Unless(err)) } return nil @@ -9465,11 +9423,6 @@ func (s *Server) jsClusteredConsumerRequest(ci *ClientInfo, acc *Account, subjec s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) return } - if cfg.DeliverPolicy != DeliverAll { - resp.Error = NewJSConsumerWQConsumerNotDeliverAllError() - s.sendAPIErrResponse(ci, acc, subject, reply, string(rmsg), s.jsonResponse(&resp)) - return - } subjects := gatherSubjectFilters(cfg.FilterSubject, cfg.FilterSubjects) for oca := range js.consumerAssignmentsOrInflightSeq(acc.Name, stream) { if oca.Name == oname || oca.Config.Direct || oca.Config.Sourcing { @@ -10025,7 +9978,7 @@ func (mset *stream) processClusteredInboundMsg(subject, reply string, hdr, msg [ // Check msgSize if we have a limit set there. Again this works if it goes through but better to be pre-emptive. // Subtract to prevent against overflows. if maxMsgSize >= 0 && (len(hdr) > maxMsgSize || len(msg) > maxMsgSize-len(hdr)) { - err := fmt.Errorf("JetStream message size exceeds limits for '%s > %s'", jsa.acc().Name, name) + err := fmt.Errorf("JetStream message size exceeds limits for '%s > %s'", jsa.acc().Name, mset.cfg.Name) s.RateLimitWarnf("%s", err.Error()) if canRespond { var resp = &JSPubAckResponse{PubAck: &PubAck{Stream: name}} @@ -10322,7 +10275,9 @@ func (mset *stream) processSnapshot(snap *StreamReplicatedState, index uint64) ( mset.mu.Lock() for _, o := range mset.consumers { o.mu.Lock() - o.streamNumPending() + if o.isLeader() { + o.streamNumPending() + } o.mu.Unlock() } mset.mu.Unlock() @@ -10507,11 +10462,8 @@ RETRY: return err } else if err == NewJSInsufficientResourcesError() { notifyLeaderStopCatchup(mrec, err) - mset.cfgMu.RLock() - storage := mset.cfg.Storage - mset.cfgMu.RUnlock() - if mset.js.limitsExceeded(storage) { - s.resourcesExceededError(storage) + if mset.js.limitsExceeded(mset.cfg.Storage) { + s.resourcesExceededError(mset.cfg.Storage) } else { s.Warnf("Catchup for stream '%s > %s' errored, account resources exceeded: %v", mset.account(), mset.name(), err) } @@ -11215,8 +11167,6 @@ func (mset *stream) runCatchup(sendSubject string, sreq *streamSyncRequest) { // Run as long as we are still active and need catchup. // FIXME(dlc) - Purge event? Stream delete? - retryTimer := time.NewTimer(500 * time.Millisecond) - defer stopAndClearTimer(&retryTimer) for { // Get this each time, will be non-nil if globally blocked and we will close to wake everyone up. cbKick := s.cbKickChan() @@ -11243,13 +11193,12 @@ func (mset *stream) runCatchup(sendSubject string, sreq *streamSyncRequest) { mset.clearCatchupPeer(sreq.Peer) return } - case <-retryTimer.C: + case <-time.After(500 * time.Millisecond): if !sendNextBatchAndContinue(qch) { mset.clearCatchupPeer(sreq.Peer) return } } - retryTimer.Reset(500 * time.Millisecond) } } diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/leafnode.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/leafnode.go index 265da58dc..be84f7b19 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/leafnode.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/leafnode.go @@ -304,13 +304,6 @@ func validateLeafNode(o *Options) error { return fmt.Errorf("remote leaf node configuration cannot have a mix of websocket and non-websocket urls: %q", redactURLList(rcfg.URLs)) } } - if !wsAllowedFIPS() { - for _, u := range rcfg.URLs { - if isWSURL(u) { - return fmt.Errorf("remote leaf node URL %q cannot be used in FIPS-140 mode when built with this Go version, use Go 1.26 or later", redactURLString(u.String())) - } - } - } // Validate compression settings if rcfg.Compression.Mode != _EMPTY_ { if err := validateAndNormalizeCompressionOption(&rcfg.Compression, CompressionS2Auto); err != nil { @@ -1307,10 +1300,7 @@ func (s *Server) createLeafNode(conn net.Conn, rURL *url.URL, remote *leafNodeCf info = s.copyLeafNodeInfo() // For tests that want to simulate old servers, do not set the compression // on the INFO protocol if configured with CompressionNotSupported. - // Also suppress it if WebSocket compression is already in use, otherwise - // an old soliciting peer would honor the advertised mode, switch to S2, - // and then wait forever for a compressed INFO response from us. - if cm := opts.LeafNode.Compression.Mode; cm != CompressionNotSupported && (ws == nil || !ws.compress) { + if cm := opts.LeafNode.Compression.Mode; cm != CompressionNotSupported { info.Compression = cm } // We always send a nonce for LEAF connections. Do not change that without @@ -1731,15 +1721,6 @@ func (c *client) processLeafnodeInfo(info *Info) { } func (s *Server) negotiateLeafCompression(c *client, didSolicit bool, infoCompression string, co *CompressionOpts) (bool, error) { - // If WebSocket compression is already negotiated on this connection then - // we shouldn't layer S2 compression on top of it. - c.mu.Lock() - if c.ws != nil && c.ws.compress { - c.leaf.compression = CompressionOff - c.mu.Unlock() - return false, nil - } - c.mu.Unlock() // Negotiate the appropriate compression mode (or no compression) cm, err := selectCompressionMode(co.Mode, infoCompression) if err != nil { @@ -2046,14 +2027,12 @@ func (s *Server) addLeafNodeConnection(c *client, srvName, clusterName string, c // In an extension use case, pin leadership to server remotes connect to. // Therefore, server with a remote that are not already in observer mode, need to be put into it. if solicited && meta != nil && !meta.IsObserver() { - c.Debugf("Turning JetStream metadata controller Observer Mode on - System Account Connected") - // Discard any local metagroup state accumulated before the SYS-account - // leaf came up (e.g. the wrong-hint case where this server bootstrapped - // its own metagroup). The parent's view is now authoritative; without - // this reset the two raft logs stay forked because the standalone log's - // commit prefix short-circuits the follower's AE handling. meta.setObserver(true, extExtended) - meta.Reset() + c.Debugf("Turning JetStream metadata controller Observer Mode on - System Account Connected") + // Take note that the domain was not extended to avoid this state next startup. + writePeerState(js.config.StoreDir, meta.currentPeerState()) + // If this server is the leader already, step down so a new leader can be elected (that is not an observer) + meta.StepDown() } } else { // This deny is needed in all cases (system account shared or not) @@ -2607,48 +2586,31 @@ func (acc *Account) updateLeafNodesEx(sub *subscription, delta int32, hubOnly bo // Do this once. subject := string(sub.subject) - // Walk the connected leafnodes from a random starting point to avoid - // concurrent callers all contending over leafs in the same order. - nleafs := len(acc.lleafs) - start := 0 - if nleafs > 1 { - start = rand.Intn(nleafs) - } - for i := 0; i < nleafs; i++ { - ln := acc.lleafs[(start+i)%nleafs] + // Walk the connected leafnodes. + for _, ln := range acc.lleafs { if ln == sub.client { continue } - ln.mu.RLock() + ln.mu.Lock() // Don't advertise interest from leafnodes to other isolated leafnodes. if sub.client.kind == LEAF && ln.isIsolatedLeafNode() { - ln.mu.RUnlock() + ln.mu.Unlock() continue } // If `hubOnly` is true, it means that we want to update only leafnodes // that connect to this server (so isHubLeafNode() would return `true`). if hubOnly && !ln.isHubLeafNode() { - ln.mu.RUnlock() + ln.mu.Unlock() continue } // Check to make sure this sub does not have an origin cluster that matches the leafnode. // If skipped, make sure that we still let go the "$LDS." subscription that allows // the detection of loops as long as different cluster. clusterDifferent := cluster != ln.remoteCluster() - update := (isLDS && clusterDifferent) || - ((cluster == _EMPTY_ || clusterDifferent) && (delta <= 0 || ln.canSubscribeInternal(subject))) - ln.mu.RUnlock() - if update { - ln.mu.Lock() - // The leaf role, isolation mode, and remote cluster are stable - // for the connection. Recheck canSubscribe here since permissions - // can change, and to initializes mperms for wildcard subscriptions - // that collide with deny rules. - if isLDS || delta <= 0 || ln.canSubscribe(subject) { - ln.updateSmap(sub, delta, isLDS) - } - ln.mu.Unlock() + if (isLDS && clusterDifferent) || ((cluster == _EMPTY_ || clusterDifferent) && (delta <= 0 || ln.canSubscribe(subject))) { + ln.updateSmap(sub, delta, isLDS) } + ln.mu.Unlock() } } @@ -3337,48 +3299,35 @@ func (c *client) leafMsgAllowed() bool { return true } - c.mu.RLock() + c.mu.Lock() + defer c.mu.Unlock() + if c.isSpokeLeafNode() { // Gateway routed replies are forwarded without // permission checks. if isGW || c.leafReceiveAllowed(subjectToCheck) { - c.mu.RUnlock() return true } } else if c.leafSendAllowed(subjectToCheck) { - c.mu.RUnlock() return true } - - // If allow_responses is not configured, or there is no tracked reply for - // this subject, the answer is "denied" and we can return it while still - // holding only the read lock. - replySubject := bytesToString(wireSubject) - if c.perms == nil || c.perms.resp == nil || c.replies[replySubject] == nil { - c.mu.RUnlock() - return false - } - c.mu.RUnlock() - // Check tracked reply permissions (allow_responses). // Use the pre-strip subject since deliverMsg tracks // replies under the original form, which includes // the GW routing prefix for routed requests. - c.mu.Lock() - defer c.mu.Unlock() - return c.responseAllowed(replySubject) + return c.responseAllowed(bytesToString(wireSubject)) } // Returns true if the leaf side ACLs allow importing this subject, // based on the permissions received over INFO and any local deny_imports. -// At least a read lock must be held. +// Lock must be held. func (c *client) leafReceiveAllowed(subject []byte) bool { - return c.canSubscribeInternal(bytesToString(subject)) + return c.canSubscribe(bytesToString(subject)) } // Returns true if the hub side ACLs allow the remote leaf to send // this subject. -// At least a read lock must be held. +// Lock must be held. func (c *client) leafSendAllowed(bsubject []byte) bool { // Use the original export ACL captured for this accepted leaf. // The live perms also contain additional JetStream denies used by diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/memstore.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/memstore.go index 9cce5cc18..4e3f113b3 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/memstore.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/memstore.go @@ -961,7 +961,7 @@ func (ms *memStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPerS var havePartial bool var totalSkipped uint64 // We will track start and end sequences as we go. - stree.IntersectGSL[SimpleState](ms.fss, sl, func(subj []byte, fss *SimpleState) bool { + stree.IntersectGSL[SimpleState](ms.fss, sl, func(subj []byte, fss *SimpleState) { if fss.firstNeedsUpdate || fss.lastNeedsUpdate { ms.recalculateForSubj(bytesToString(subj), fss) } @@ -975,7 +975,6 @@ func (ms *memStore) NumPendingMulti(sseq uint64, sl *gsl.SimpleSublist, lastPerS } else { totalSkipped += fss.Msgs } - return true }) // If we did not encounter any partials we can return here. @@ -2596,15 +2595,13 @@ func (o *consumerMemStore) UpdateAcks(dseq, sseq uint64) error { return ErrNoAckPolicy } - // We do this regardless. - delete(o.state.Redelivered, sseq) - // On restarts the old leader may get a replay from the raft logs that are old. if dseq <= o.state.AckFloor.Consumer { return nil } if len(o.state.Pending) == 0 || o.state.Pending[sseq] == nil { + delete(o.state.Redelivered, sseq) return ErrStoreMsgNotFound } @@ -2658,23 +2655,12 @@ func (o *consumerMemStore) UpdateAcks(dseq, sseq uint64) error { } } } + // We do these regardless. + delete(o.state.Redelivered, sseq) return nil } -func (o *consumerMemStore) RemoveRedeliveredBelow(seq uint64) { - if seq == 0 { - return - } - o.mu.Lock() - defer o.mu.Unlock() - for s := range o.state.Redelivered { - if s < seq { - delete(o.state.Redelivered, s) - } - } -} - func (o *consumerMemStore) UpdateConfig(cfg *ConsumerConfig) error { o.mu.Lock() defer o.mu.Unlock() diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/monitor.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/monitor.go index 326c0855b..6d4460b23 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/monitor.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/monitor.go @@ -1271,14 +1271,10 @@ type Varz struct { Routes int `json:"routes"` // Routes is the number of connected route servers Remotes int `json:"remotes"` // Remotes is the configured route remote endpoints Leafs int `json:"leafnodes"` // Leafs is the number connected leafnode clients - InMsgs int64 `json:"in_msgs"` // InMsgs is the total number of messages this server received. This includes messages from the clients, routers, gateways and leaf nodes - InBytes int64 `json:"in_bytes"` // InBytes is the total number of bytes this server received. This includes messages from the clients, routers, gateways and leaf nodes - InClientMsgs int64 `json:"in_client_msgs"` // InClientMsgs is the number of messages this server received from the clients - InClientBytes int64 `json:"in_client_bytes"` // InClientBytes is the number of bytes this server received from the clients - OutMsgs int64 `json:"out_msgs"` // OutMsgs is the total number of message this server sent. This includes messages sent to the clients, routers, gateways and leaf nodes - OutBytes int64 `json:"out_bytes"` // OutBytes is the total number of bytes this server sent. This includes messages sent to the clients, routers, gateways and leaf nodes - OutClientMsgs int64 `json:"out_client_msgs"` // OutClientMsgs is the number of messages this server sent to the clients - OutClientBytes int64 `json:"out_client_bytes"` // OutClientBytes is the number of bytes this server sent to the clients + InMsgs int64 `json:"in_msgs"` // InMsgs is the number of messages this server received + OutMsgs int64 `json:"out_msgs"` // OutMsgs is the number of message this server sent + InBytes int64 `json:"in_bytes"` // InBytes is the number of bytes this server received + OutBytes int64 `json:"out_bytes"` // OutMsgs is the number of bytes this server sent SlowConsumers int64 `json:"slow_consumers"` // SlowConsumers is the total count of clients that were disconnected since start due to being slow consumers StaleConnections int64 `json:"stale_connections"` // StaleConnections is the total count of stale connections that were detected StalledClients int64 `json:"stalled_clients"` // StalledClients is the total number of times that clients have been stalled. @@ -1881,10 +1877,6 @@ func (s *Server) updateVarzRuntimeFields(v *Varz, forceUpdate bool, pcpu float64 v.InBytes = atomic.LoadInt64(&s.inBytes) v.OutMsgs = atomic.LoadInt64(&s.outMsgs) v.OutBytes = atomic.LoadInt64(&s.outBytes) - v.InClientMsgs = atomic.LoadInt64(&s.inClientMsgs) - v.InClientBytes = atomic.LoadInt64(&s.inClientBytes) - v.OutClientMsgs = atomic.LoadInt64(&s.outClientMsgs) - v.OutClientBytes = atomic.LoadInt64(&s.outClientBytes) v.SlowConsumers = atomic.LoadInt64(&s.slowConsumers) v.StalledClients = atomic.LoadInt64(&s.stalls) v.SlowConsumersStats = &SlowConsumersStats{ diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/mqtt.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/mqtt.go index 4ff181b2a..7b0e5c2fd 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/mqtt.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/mqtt.go @@ -239,7 +239,7 @@ var ( errMQTTEmptyUsername = errors.New("empty user name not allowed") errMQTTTopicIsEmpty = errors.New("topic cannot be empty") errMQTTPacketIdentifierIsZero = errors.New("packet identifier cannot be 0") - errMQTTUnsupportedCharacters = errors.New("character not supported for MQTT topics") + errMQTTUnsupportedCharacters = errors.New("character ' ' not supported for MQTT topics") errMQTTInvalidSession = errors.New("invalid MQTT session") errMQTTInvalidRetainFlags = errors.New("invalid retained message flags") errMQTTSessionCollision = errors.New("stored session does not match client ID") @@ -5713,11 +5713,8 @@ func mqttToNATSSubjectConversion(mt []byte, wcOk bool) ([]byte, error) { } res = append(res, btsep) } - case ' ', '\t', '\n', '\r', '\f': - // We cannot support whitespace in the MQTT topic/filter — these - // characters would also corrupt the NATS wire protocol when the - // subject is forwarded to other connection types (e.g. leaf - // nodes) where the resulting control line could be split. + case ' ': + // As of now, we cannot support ' ' in the MQTT topic/filter. return nil, errMQTTUnsupportedCharacters case 0x7f: // SubjectTree uses DEL as an internal pivot marker, so retained diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/raft.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/raft.go index 9f33e1928..5055297e7 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/raft.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/raft.go @@ -86,7 +86,6 @@ type RaftNode interface { WaitForStop() Delete() IsDeleted() bool - Reset() RecreateInternalSubs() error IsSystemAccount() bool GetTrafficAccountName() string @@ -345,7 +344,6 @@ var ( errNoInternalClient = errors.New("raft: no internal client") errMembershipChange = errors.New("raft: membership change in progress") errRemoveLastNode = errors.New("raft: cannot remove the last peer") - errPeerNotFound = errors.New("raft: peer not found") ) // This will bootstrap a raftNode by writing its config into the store directory. @@ -1048,10 +1046,7 @@ func (n *raft) ProposeRemovePeer(peer string) error { n.RUnlock() return errMembershipChange } - if _, ok := n.peers[peer]; !ok { - n.RUnlock() - return errPeerNotFound - } + if len(n.peers) <= 1 { n.RUnlock() return errRemoveLastNode @@ -1388,11 +1383,6 @@ func (n *raft) installSnapshot(snap *snapshot) error { return err } - // If installing a snapshot past our commits, clear the cache. - if snap.lastIndex > n.commit && len(n.pae) > 0 { - n.pae = make(map[uint64]*appendEntry) - } - var state StreamState n.wal.FastState(&state) n.papplied = snap.lastIndex @@ -1553,20 +1543,12 @@ func (c *checkpoint) InstallSnapshot(data []byte) (uint64, error) { n.Unlock() err := writeFileWithSync(c.snapFile, encoded, defaultFilePerms) n.Lock() - // On either failure path, drop the file we just wrote so it doesn't get - // picked up by setupLastSnapshot on restart. Skip the remove if it's the - // snapshot already adopted into n.snapfile for this term/applied. if err != nil { - if c.snapFile != n.snapfile { - os.Remove(c.snapFile) - } // We could set write err here, but if this is a temporary situation, too many open files etc. // we want to retry and snapshots are not fatal. return 0, err } else if !n.snapshotting { - if c.snapFile != n.snapfile { - os.Remove(c.snapFile) - } + // The checkpoint can be aborted at any time, don't continue if that happened. return 0, errSnapAborted } @@ -1628,9 +1610,6 @@ func termAndIndexFromSnapFile(sn string) (term, index uint64, err error) { if n, err := fmt.Sscanf(fn, snapFileT, &term, &index); err != nil || n != 2 { return 0, 0, errBadSnapName } - if fn != fmt.Sprintf(snapFileT, term, index) { - return 0, 0, errBadSnapName - } return term, index, nil } @@ -2241,64 +2220,6 @@ func (n *raft) shutdown() { } } -// Reset discards this node's local raft state (log, snapshots, peer set, -// term/vote) so it can be caught up cleanly by another group with the same -// name. The caller is responsible for parking the node first (typically via -// SetObserver) if it should not compete for leadership immediately after; -// Reset itself steps the node down but does not flip observer mode. -func (n *raft) Reset() { - n.Lock() - defer n.Unlock() - - n.debug("Resetting Raft state") - - n.stepdownLocked(_EMPTY_) - - // Cancel any in-flight catchup so it does not race the reset. - n.cancelCatchup() - - // Drop proposals and inbound entries; they are no longer meaningful - // against whatever log this node ends up following. - n.prop.drain() - n.entry.drain() - n.resp.drain() - n.apply.drain() - n.reqs.drain() - n.votes.drain() - - // Remove every snapshot under our snapshots dir, not just the one referenced - // by n.snapfile. Orphans (e.g. from a crash between install and the previous - // file's removal) would otherwise be picked up by setupLastSnapshot on the - // next restart and reseed the state we are discarding here. - snapDir := filepath.Join(n.sd, snapshotsDir) - if err := os.RemoveAll(snapDir); err != nil { - n.warn("Error removing snapshots directory during reset: %v", err) - } - if err := os.MkdirAll(snapDir, defaultDirPerms); err != nil { - n.warn("Error recreating snapshots directory during reset: %v", err) - } - n.snapfile = _EMPTY_ - - // Abort any inflight async snapshot checkpoint. - n.snapshotting = false - - // Reset the WAL, but reset these first to not trip the assertion. - n.commit, n.hcommit, n.applied, n.processed, n.papplied = 0, 0, 0, 0, 0 - n.resetWAL() - - // Reset peer set to just ourselves; a new leader will fold us back into - // the cluster's membership view via processPeerState. - n.peers = map[string]*lps{n.id: {time.Time{}, 0, true}} - n.removed = nil - n.adjustClusterSizeAndQuorum() - - n.term, n.vote = 0, _EMPTY_ - n.writeTermVote() - - // Persist the cleared peer state so a restart picks up the reset. - n.writePeerState(n.currentPeerStateLocked()) -} - const ( raftAllSubj = "$NRG.>" raftVoteSubj = "$NRG.V.%s" @@ -2983,16 +2904,6 @@ func (n *raft) handleForwardedRemovePeerProposal(sub *subscription, c *client, _ n.RUnlock() return } - if _, ok := n.peers[string(msg)]; !ok { - n.debug("Ignoring forwarded peer removal proposal, peer not found") - n.RUnlock() - return - } - if len(n.peers) <= 1 { - n.debug("Ignoring forwarded peer removal proposal, remove last node") - n.RUnlock() - return - } prop := n.prop n.RUnlock() @@ -3990,19 +3901,6 @@ func (n *raft) truncateWAL(term, index uint64) { // Set after we know we have truncated properly. n.pterm, n.pindex = term, index - // Invalidate cached entries the WAL no longer has. - if index == 0 { - if len(n.pae) > 0 { - n.pae = make(map[uint64]*appendEntry) - } - } else { - for k := range n.pae { - if k > index { - delete(n.pae, k) - } - } - } - // Check if we're truncating an uncommitted membership change. if n.membChangeIndex > 0 && n.membChangeIndex > index { n.membChangeIndex = 0 @@ -4357,10 +4255,13 @@ func (n *raft) processAppendEntry(ae *appendEntry, sub *subscription) { // Inherit state from appendEntry with the leader's snapshot. hadPreviousSnapshot := n.snapfile != _EMPTY_ + n.pindex = ae.pindex + n.pterm = ae.pterm + n.commit = ae.pindex snap := &snapshot{ - lastTerm: ae.pterm, - lastIndex: ae.pindex, + lastTerm: n.pterm, + lastIndex: n.pindex, peerstate: encodePeerState(&peerState{n.peerNames(), n.csz, n.extSt}), data: ae.entries[0].Data, } @@ -4370,9 +4271,6 @@ func (n *raft) processAppendEntry(ae *appendEntry, sub *subscription) { n.Unlock() return } - n.pindex = ae.pindex - n.pterm = ae.pterm - n.commit = ae.pindex n.resetInitializing() if !hadPreviousSnapshot { diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/route.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/route.go index 19fd13c80..a0384ad35 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/route.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/route.go @@ -2015,7 +2015,7 @@ func (s *Server) createRoute(conn net.Conn, rURL *url.URL, rtype RouteType, goss pingInterval = opts.Cluster.PingInterval } if opts.Cluster.MaxPingsOut > 0 { - pingMax = opts.Cluster.MaxPingsOut + pingMax = opts.MaxPingsOut } c.watchForStaleConnection(adjustPingInterval(ROUTER, pingInterval), pingMax) } else { diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/server.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/server.go index 411102f17..9612c868c 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/server.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/server.go @@ -402,13 +402,9 @@ type nodeInfo struct { type stats struct { inMsgs int64 - inBytes int64 - inClientMsgs int64 - inClientBytes int64 outMsgs int64 + inBytes int64 outBytes int64 - outClientMsgs int64 - outClientBytes int64 slowConsumers int64 staleConnections int64 stalls int64 @@ -2559,10 +2555,6 @@ func (s *Server) Shutdown() { if s == nil { return } - // Prevent issues with multiple calls. - if !s.shutdown.CompareAndSwap(false, true) { - return - } // This is for JetStream R1 Pull Consumers to allow signaling // that pending pull requests are invalid. s.signalPullConsumers() @@ -2576,6 +2568,11 @@ func (s *Server) Shutdown() { // eventing items associated with accounts. s.shutdownEventing() + // Prevent issues with multiple calls. + if s.isShuttingDown() { + return + } + s.mu.Lock() s.Noticef("Initiating Shutdown...") @@ -2583,6 +2580,7 @@ func (s *Server) Shutdown() { opts := s.getOpts() + s.shutdown.Store(true) s.running.Store(false) s.grMu.Lock() s.grRunning = false @@ -3413,12 +3411,8 @@ func (s *Server) createClientEx(conn net.Conn, inProcess bool) *client { } } - // Check for proxy protocol if enabled. The PROXY header is sent as - // plaintext before any TLS handshake per the spec, so we must read it - // before doing TLS even when TLS is required. Any bytes read past the - // header are kept in `pre` and replayed into the TLS handshake (or the - // non-TLS protocol parser) by the tlsMixConn wrapper used below. - if !isClosed && opts.ProxyProtocol { + // Check for proxy protocol if enabled. + if !isClosed && !tlsRequired && opts.ProxyProtocol { if len(pre) == 0 { // There has been no pre-read yet, do so so we can work out // if the client is trying to negotiate PROXY. @@ -3646,11 +3640,7 @@ func tlsTimeout(c *client, conn *tls.Conn) { } cs := conn.ConnectionState() if !cs.HandshakeComplete { - if c.kind == CLIENT || c.kind == LEAF { - c.Debugf("TLS handshake timeout") - } else { - c.Errorf("TLS handshake timeout") - } + c.Errorf("TLS handshake timeout") c.sendErr("Secure Connection - TLS Required") c.closeConnection(TLSHandshakeError) } diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/store.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/store.go index f30eddcdd..31a834efa 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/store.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/store.go @@ -364,7 +364,6 @@ type ConsumerStore interface { HasState() bool UpdateDelivered(dseq, sseq, dc uint64, ts int64) error UpdateAcks(dseq, sseq uint64) error - RemoveRedeliveredBelow(seq uint64) UpdateConfig(cfg *ConsumerConfig) error Update(*ConsumerState) error ForceUpdate(*ConsumerState) error diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/stream.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/stream.go index 03ac8b2de..5698f3cb2 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/stream.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/stream.go @@ -264,7 +264,7 @@ type PubAck struct { Duplicate bool `json:"duplicate,omitempty"` Value string `json:"val,omitempty"` BatchId string `json:"batch,omitempty"` - BatchSize uint64 `json:"count,omitempty"` + BatchSize int `json:"count,omitempty"` } // CounterValue is the body of a message when used as a counter. @@ -571,7 +571,6 @@ type stream struct { mirrorLastBySub *subscription // Mirrors only. monitorWg sync.WaitGroup // Wait group for the monitor routine. - monitorMu sync.Mutex // Serializes monitorWg's Add against Wait to prevent a WaitGroup reuse panic. // If standalone/single-server, the offline reason needs to be stored directly in the stream. // Otherwise, if clustered it will be part of the stream assignment. @@ -583,9 +582,8 @@ type stream struct { // inflightSubjectRunningTotal stores a running total of inflight messages for a specific subject. type inflightSubjectRunningTotal struct { - bytes uint64 // Running total of inflight bytes for inflight messages. - ops uint64 // Inflight operations, i.e. inflight messages for this subject. If this reaches zero, we can remove the running total. - schedule bool // Marks whether the last message is a schedule. + bytes uint64 // Running total of inflight bytes for inflight messages. + ops uint64 // Inflight operations, i.e. inflight messages for this subject. If this reaches zero, we can remove the running total. } // msgCounterRunningTotal stores a running total and a number of inflight @@ -818,7 +816,7 @@ func (a *Account) addStreamWithAssignment(config *StreamConfig, fsConfig *FileSt if isClustered { _, reserved = js.tieredStreamAndReservationCount(a.Name, tier, cfg) } - if err := js.checkAllLimits(&selected, tier, cfg, reserved, 0); err != nil { + if err := js.checkAllLimits(&selected, cfg, reserved, 0); err != nil { js.mu.RUnlock() return nil, err } @@ -2342,10 +2340,11 @@ func (jsa *jsAccount) configUpdateCheck(old, new *StreamConfig, s *Server, pedan // Save the user configured MaxBytes. newMaxBytes := cfg.MaxBytes + maxBytesOffset := int64(0) // We temporarily set cfg.MaxBytes to maxBytesDiff because checkAllLimits // adds cfg.MaxBytes to the current reserved limit and checks if we've gone - // over. However, we don't want an additional cfg.MaxBytes, we only want to + // over. However, we don't want an addition cfg.MaxBytes, we only want to // reserve the difference between the new and the old values. cfg.MaxBytes = maxBytesDiff @@ -2372,13 +2371,15 @@ func (jsa *jsAccount) configUpdateCheck(old, new *StreamConfig, s *Server, pedan if isClustered { _, reserved = js.tieredStreamAndReservationCount(acc.Name, tier, &cfg) } - // reserved covers only the other streams. checkAllLimits adds this stream's - // footprint via cfg.MaxBytes, which is currently maxBytesDiff, so it only - // adds the diff. Add the remaining (newMaxBytes - maxBytesDiff) here so the - // two together equal this stream's true new footprint, even when Replicas - // changes on update. - reserved = addSaturate(reserved, accountReservation(tier, cfg.Replicas, newMaxBytes-maxBytesDiff)) - if err := js.checkAllLimits(&selected, tier, &cfg, reserved, 0); err != nil { + // reservation does not account for this stream, hence add the old value + if old.MaxBytes > 0 { + if tier == _EMPTY_ && old.Replicas > 1 { + reserved = addSaturate(reserved, mulSaturate(int64(old.Replicas), old.MaxBytes)) + } else { + reserved = addSaturate(reserved, old.MaxBytes) + } + } + if err := js.checkAllLimits(&selected, &cfg, reserved, maxBytesOffset); err != nil { return nil, err } // Restore the user configured MaxBytes. @@ -3017,20 +3018,14 @@ func (mset *stream) retryDisconnectedSyncConsumers() { clientClosed := func(c *client) bool { return c != nil && (c.flags.isSet(closeConnection) || c.flags.isSet(connMarkedClosed)) } - // Stale sources need to be reset: if not seen past the health check interval, it's stale. + // Stale sources need to be reset: we expect a heartbeat every sourceHealthHB, so missing a couple + // is a strong signal the remote delivery is no longer reaching us and a retry is warranted. stale := func(si *sourceInfo) bool { - return time.Since(time.Unix(0, si.last.Load())) > sourceHealthCheckInterval + return time.Since(time.Unix(0, si.last.Load())) > 2*sourceHealthHB } shouldRetry := func(si *sourceInfo) bool { - if si != nil && !si.sip && (si.sub == nil || clientClosed(si.sub.client) || stale(si)) { - // Skip if a recreate is already scheduled and we can't cancel it. - if t, ok := mset.sourceSetupSchedules[si.iname]; ok { - if !t.Stop() { - return false - } - delete(mset.sourceSetupSchedules, si.iname) - } - si.fails = 0 + if si != nil && (si.sip || si.sub == nil || clientClosed(si.sub.client) || stale(si)) { + si.fails, si.sip = 0, false mset.cancelSourceInfo(si) return true } @@ -3210,13 +3205,7 @@ func (mset *stream) processInboundMirrorMsg(m *inMsg) bool { } else { // If the deliver sequence matches then the upstream stream has expired or deleted messages. if dseq == mset.mirror.dseq+1 { - if err := mset.skipMsgs(mset.mirror.sseq+1, sseq-1); err != nil { - mset.mirror.sseq = osseq - mset.mirror.dseq = odseq - mset.mu.Unlock() - mset.retryMirrorConsumer() - return false - } + mset.skipMsgs(mset.mirror.sseq+1, sseq-1) mset.mirror.dseq++ mset.mirror.sseq = sseq } else { @@ -3274,7 +3263,7 @@ func (mset *stream) processInboundMirrorMsg(m *inMsg) bool { if err != nil { if strings.Contains(err.Error(), "no space left") { s.Errorf("JetStream out of space, will be DISABLED") - s.ShutdownJetStream() + s.DisableJetStream() return false } if err != errLastSeqMismatch { @@ -3285,18 +3274,20 @@ func (mset *stream) processInboundMirrorMsg(m *inMsg) bool { accName, sname, err) } else { // We may have missed messages, restart. - lseq := mset.lastSeq() - mset.mu.Lock() - if mset.mirror != nil { + if lseq := mset.lastSeq(); sseq <= lseq { + mset.mu.Lock() mset.mirror.lag = olag + mset.mirror.sseq = lseq + mset.mirror.dseq = odseq + mset.mu.Unlock() + return false + } else { + mset.mu.Lock() mset.mirror.dseq = odseq mset.mirror.sseq = osseq - if sseq <= lseq { - mset.mirror.sseq = lseq - } + mset.mu.Unlock() + mset.retryMirrorConsumer() } - mset.mu.Unlock() - mset.retryMirrorConsumer() } } return err == nil @@ -3333,21 +3324,20 @@ func (mset *stream) retryMirrorConsumer() error { } // Lock should be held. -func (mset *stream) skipMsgs(start, end uint64) error { +func (mset *stream) skipMsgs(start, end uint64) { node, store := mset.node, mset.store // If we are not clustered we can short circuit now with store.SkipMsgs if node == nil { - if err := store.SkipMsgs(start, end-start+1); err != nil { - return err - } + store.SkipMsgs(start, end-start+1) mset.lseq = end - return nil + return } // Must only be enabled once every peer in the cluster supports receiving // deleteRangeOp in the normal apply path; older peers panic on unknown ops. if mset.srv.getOpts().getFeatureFlag(FeatureFlagJsRaftDeleteRange) { - return node.Propose(encodeDeleteRange(&DeleteRange{First: start, Num: end - start + 1})) + node.Propose(encodeDeleteRange(&DeleteRange{First: start, Num: end - start + 1})) + return } var entries []*Entry @@ -3355,9 +3345,7 @@ func (mset *stream) skipMsgs(start, end uint64) error { entries = append(entries, newEntry(EntryNormal, encodeStreamMsg(_EMPTY_, _EMPTY_, nil, nil, seq-1, 0, false))) // So a single message does not get too big. if len(entries) > 10_000 { - if err := node.ProposeMulti(entries); err != nil { - return err - } + node.ProposeMulti(entries) // We need to re-create `entries` because there is a reference // to it in the node's pae map. entries = entries[:0] @@ -3365,9 +3353,8 @@ func (mset *stream) skipMsgs(start, end uint64) error { } // Send all at once. if len(entries) > 0 { - return node.ProposeMulti(entries) + node.ProposeMulti(entries) } - return nil } const ( @@ -3731,25 +3718,13 @@ func (mset *stream) setupMirrorConsumer() error { state = StreamState{} mset.store.FastState(&state) if state.LastSeq < ccr.ConsumerInfo.Delivered.Stream { - // Local helper: abort consumer setup, leaving the mirror in its - // pre-setup state so the retry path can re-create it cleanly. - failSetup := func(setupErr error) { - mset.cancelSourceInfo(mirror) - mirror.err = NewJSMirrorConsumerSetupFailedError(setupErr, Unless(setupErr)) - retry = true - mset.mu.Unlock() - } // Check to see if delivered is past our last and we have no msgs. This will help the // case when mirroring a stream that has a very high starting sequence number. if state.Msgs == 0 && ccr.ConsumerInfo.Delivered.Stream > state.LastSeq { - if _, err := mset.store.PurgeEx(_EMPTY_, ccr.ConsumerInfo.Delivered.Stream+1, 0); err != nil { - failSetup(err) - return - } + mset.store.PurgeEx(_EMPTY_, ccr.ConsumerInfo.Delivered.Stream+1, 0) mset.lseq = ccr.ConsumerInfo.Delivered.Stream - } else if err := mset.skipMsgs(state.LastSeq+1, ccr.ConsumerInfo.Delivered.Stream); err != nil { - failSetup(err) - return + } else { + mset.skipMsgs(state.LastSeq+1, ccr.ConsumerInfo.Delivered.Stream) } } @@ -4424,7 +4399,7 @@ func (mset *stream) processInboundSourceMsg(si *sourceInfo, m *inMsg) bool { s := mset.srv if strings.Contains(err.Error(), "no space left") { s.Errorf("JetStream out of space, will be DISABLED") - s.ShutdownJetStream() + s.DisableJetStream() } else { mset.mu.RLock() accName, sname, iName := mset.acc.Name, mset.cfg.Name, si.iname @@ -5044,14 +5019,10 @@ func (mset *stream) deleteAtomicBatches(shuttingDown bool) { // Lock should be held. func (mset *stream) deleteBatchApplyState() { if batch := mset.batchApply; batch != nil { - // Clear under batch.mu so a stale reference held by the stream monitor - // can't re-pool entries we already returned. - batch.mu.Lock() + // Need to return entries (if any) to the pool. for _, bce := range batch.entries { bce.ReturnToPool() } - batch.clearBatchStateLocked() - batch.mu.Unlock() mset.batchApply = nil } } @@ -5205,12 +5176,9 @@ func (mset *stream) storeUpdates(md, bd int64, seq uint64, subj string) { mset.clsMu.RUnlock() } else if md < 0 { // Batch decrements we need to force consumers to re-calculate num pending. - var ss StreamState - mset.store.FastState(&ss) mset.clsMu.RLock() for _, o := range mset.cList { o.streamNumPendingLocked() - o.removeRedeliveredBelow(ss.FirstSeq) } mset.clsMu.RUnlock() } @@ -5590,14 +5558,15 @@ func getFastBatch(reply string, hdr []byte) (*FastBatch, bool) { if o = strings.LastIndexByte(reply[:o], '.'); o == -1 { return nil, true } - seq, ok := parseUint64(stringToBytes(reply[o+1 : p])) - // Reject math.MaxUint64 to prevent b.lseq overflowing on the next b.lseq++. - if !ok || seq == 0 || seq == math.MaxUint64 { + a := parseInt64(stringToBytes(reply[o+1 : p])) + if a < 1 { return nil, true } - b.seq = seq + b.seq = uint64(a) p = o - if b.seq == 1 && b.commitEob { + if b.seq <= 0 { + return nil, true + } else if b.seq == 1 && b.commitEob { return nil, true } if op == FastBatchOpStart && b.seq != 1 { @@ -5621,7 +5590,7 @@ func getFastBatch(reply string, hdr []byte) (*FastBatch, bool) { if o = strings.LastIndexByte(reply[:o], '.'); o == -1 { return nil, true } - a := parseInt64(stringToBytes(reply[o+1 : p])) + a = parseInt64(stringToBytes(reply[o+1 : p])) if a <= 0 { a = 10 } else if a > math.MaxUint16 { @@ -5644,7 +5613,7 @@ func getBatchSequence(hdr []byte) (uint64, bool) { if len(bseq) == 0 { return 0, false } - return parseUint64(bseq) + return uint64(parseInt64(bseq)), true } // Signal if we are clustered. Will acquire rlock. @@ -6559,23 +6528,6 @@ func (mset *stream) processJetStreamMsgWithBatch(subject, reply string, hdr, msg outq.sendMsg(reply, b) } return apiErr - } else { - // Check that the to-be-purged subject is a schedule message. - // We still allow this message through if there exists no message for this subject, - // to remain backward-compatible. An "expected at sequence" check can still be - // performed to make this stricter. - var smv StoreMsg - sm, _ := store.LoadLastMsg(bytesToString(scheduler), &smv) - if sm != nil && len(sliceHeader(JSSchedulePattern, sm.hdr)) == 0 { - apiErr := NewJSMessageSchedulesSchedulerInvalidError() - if canRespond { - resp.PubAck = &PubAck{Stream: name} - resp.Error = apiErr - b, _ := json.Marshal(resp) - outq.sendMsg(reply, b) - } - return apiErr - } } } else if !sourced && len(sliceHeader(JSScheduler, hdr)) > 0 { // Clients may only use Nats-Scheduler alongside Nats-Schedule-Next. @@ -6890,10 +6842,6 @@ func (mset *stream) processJetStreamMsgWithBatch(subject, reply string, hdr, msg var thdrsOnly bool if mset.tr != nil { tsubj, _ = mset.tr.Match(subject) - if tsubj != _EMPTY_ && !IsValidPublishSubject(tsubj) { - s.RateLimitWarnf("Stream '%s > %s' suppressing republish with invalid subject %q", accName, name, tsubj) - tsubj = _EMPTY_ // ... stops the republish. - } if mset.cfg.RePublish != nil { thdrsOnly = mset.cfg.RePublish.HeadersOnly } @@ -6962,7 +6910,7 @@ func (mset *stream) processJetStreamMsgWithBatch(subject, reply string, hdr, msg if isPermissionError(err) { // messages in block cache could be lost in the worst case. // In the clustered mode it is very highly unlikely as a result of replication. - go mset.srv.ShutdownJetStream() + go mset.srv.DisableJetStream() mset.srv.Warnf("Filesystem permission denied while writing msg, disabling JetStream: %v", err) return err } @@ -8214,7 +8162,10 @@ func (mset *stream) resetAndWaitOnConsumers() { node.StepDown() node.Stop() } - o.stopMonitoring() + if o.isMonitorRunning() { + o.signalMonitorQuit() + o.monitorWg.Wait() + } } } @@ -8318,7 +8269,8 @@ func (mset *stream) stop(deleteFlag, advisory bool) error { // but should we log? o.stopWithFlags(deleteFlag, deleteFlag, false, advisory) if !isShuttingDown { - o.stopMonitoring() + o.signalMonitorQuit() + o.monitorWg.Wait() } } } @@ -9048,7 +9000,7 @@ func (a *Account) RestoreStream(ncfg *StreamConfig, r io.Reader) (*stream, error } bc += hdr.Size js.mu.RLock() - err = js.checkAllLimits(&selected, tier, &cfg, reserved, bc) + err = js.checkAllLimits(&selected, &cfg, reserved, bc) js.mu.RUnlock() if err != nil { return nil, err @@ -9224,28 +9176,6 @@ func (mset *stream) checkConsumerReplication() { } } -// startMonitorWg registers a pending monitor goroutine on monitorWg. It is -// held under monitorMu so that the monitorWg.Add can never race a concurrent -// monitorWg.Wait in stopMonitoring. The corresponding monitorWg.Done is done by -// the monitor goroutine directly and must not be wrapped with monitorMu. -func (mset *stream) startMonitorWg() { - mset.monitorMu.Lock() - mset.monitorWg.Add(1) - mset.monitorMu.Unlock() -} - -// stopMonitoring signals any running monitor goroutine to quit and waits for -// it to fully exit. -func (mset *stream) stopMonitoring() { - // monitorMu is held across both the quit signal and the wait so that a - // concurrent startMonitorWg cannot slip a new monitor generation in - // between. - mset.monitorMu.Lock() - defer mset.monitorMu.Unlock() - mset.signalMonitorQuit() - mset.monitorWg.Wait() -} - // Will check if we are running in the monitor already and if not set the appropriate flag. func (mset *stream) checkInMonitor() bool { mset.mu.Lock() diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/stree/stree.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/stree/stree.go index 0c257435d..00ebdc46f 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/stree/stree.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/stree/stree.go @@ -485,7 +485,7 @@ func LazyIntersect[TL, TR any](tl *SubjectTree[TL], tr *SubjectTree[TR], cb func // IntersectGSL will match all items in the given subject tree that // have interest expressed in the given sublist. The callback will only be called // once for each subject, regardless of overlapping subscriptions in the sublist. -func IntersectGSL[T any, SL comparable](t *SubjectTree[T], sl *gsl.GenericSublist[SL], cb func(subject []byte, val *T) bool) { +func IntersectGSL[T any, SL comparable](t *SubjectTree[T], sl *gsl.GenericSublist[SL], cb func(subject []byte, val *T)) { if t == nil || t.root == nil || sl == nil { return } @@ -493,14 +493,14 @@ func IntersectGSL[T any, SL comparable](t *SubjectTree[T], sl *gsl.GenericSublis _intersectGSL(t.root, _pre[:0], sl, cb) } -func _intersectGSL[T any, SL comparable](n node, pre []byte, sl *gsl.GenericSublist[SL], cb func(subject []byte, val *T) bool) bool { +func _intersectGSL[T any, SL comparable](n node, pre []byte, sl *gsl.GenericSublist[SL], cb func(subject []byte, val *T)) { if n.isLeaf() { ln := n.(*leaf[T]) subj := append(pre, ln.suffix...) if sl.HasInterest(bytesToString(subj)) { - return cb(subj, &ln.value) + cb(subj, &ln.value) } - return true + return } bn := n.base() pre = append(pre, bn.prefix...) @@ -512,11 +512,8 @@ func _intersectGSL[T any, SL comparable](n node, pre []byte, sl *gsl.GenericSubl if !hasInterestForTokens(sl, subj, len(pre)) { continue } - if !_intersectGSL(cn, pre, sl, cb) { - return false - } + _intersectGSL(cn, pre, sl, cb) } - return true } // The subject tree can return partial tokens so we need to check starting interest diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/sublist.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/sublist.go index 8428f9dfb..7423be0b2 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/sublist.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/sublist.go @@ -638,10 +638,9 @@ func (s *Sublist) hasInterest(subject string, doLock bool, np, nq *int) bool { if doLock { s.RLock() } - var matched, ok bool + var matched bool if s.cache != nil { - var r *SublistResult - if r, ok = s.cache[subject]; ok { + if r, ok := s.cache[subject]; ok { if np != nil && nq != nil { *np += len(r.psubs) for _, qsub := range r.qsubs { @@ -654,9 +653,9 @@ func (s *Sublist) hasInterest(subject string, doLock bool, np, nq *int) bool { if doLock { s.RUnlock() } - if ok { + if matched { atomic.AddUint64(&s.cacheHits, 1) - return matched + return true } tsa := [32]string{} diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/util.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/util.go index f2c5f80d3..ff90838bb 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/util.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/util.go @@ -124,26 +124,6 @@ func parseInt64(d []byte) (n int64) { return n } -// parseUint64 expects decimal positive numbers. Returns the value and true on success, -// or 0 and false on invalid input or overflow. -func parseUint64(d []byte) (uint64, bool) { - if len(d) == 0 { - return 0, false - } - var n uint64 - for _, dec := range d { - if dec < asciiZero || dec > asciiNine { - return 0, false - } - digit := uint64(dec) - asciiZero - if n > math.MaxUint64/10 || (n == math.MaxUint64/10 && digit > math.MaxUint64%10) { - return 0, false - } - n = n*10 + digit - } - return n, true -} - // Helper to move from float seconds to time.Duration func secondsToDuration(seconds float64) time.Duration { ttl := seconds * float64(time.Second) diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket.go index c5963c6f2..0ee1ca7db 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket.go @@ -1,4 +1,4 @@ -// Copyright 2020-2026 The NATS Authors +// Copyright 2020-2025 The NATS Authors // 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 @@ -16,6 +16,7 @@ package server import ( "bytes" crand "crypto/rand" + "crypto/sha1" "crypto/tls" "encoding/base64" "encoding/binary" @@ -1106,6 +1107,15 @@ func wsGetHostAndPort(tls bool, hostport string) (string, string, error) { return strings.ToLower(host), port, err } +// Concatenate the key sent by the client with the GUID, then computes the SHA1 hash +// and returns it as a based64 encoded string. +func wsAcceptKey(key string) string { + h := sha1.New() + h.Write([]byte(key)) + h.Write(wsGUID) + return base64.StdEncoding.EncodeToString(h.Sum(nil)) +} + func wsMakeChallengeKey() (string, error) { p := make([]byte, 16) if _, err := io.ReadFull(crand.Reader, p); err != nil { @@ -1121,9 +1131,6 @@ func validateWebsocketOptions(o *Options) error { if wo.Port == 0 { return nil } - if !wsAllowedFIPS() { - return fmt.Errorf("websocket: cannot be used in FIPS-140 mode when built with this Go version, use Go 1.26 or later") - } // Enforce TLS... unless NoTLS is set to true. if wo.TLSConfig == nil && !wo.NoTLS { return errors.New("websocket requires TLS configuration") diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket_go125.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket_go125.go deleted file mode 100644 index 3bbdfe972..000000000 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket_go125.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2026 The NATS Authors -// 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. - -//go:build !go1.26 - -package server - -import ( - "crypto/fips140" - "crypto/sha1" - "encoding/base64" -) - -func wsAllowedFIPS() bool { - // SHA-1 is not permitted on Go 1.25 FIPS builds because we cannot avoid its - // enforcement for Sec-WebSocket-Key and Sec-WebSocket-Accept, it will result - // in a panic. - return !fips140.Enabled() -} - -// Concatenate the key sent by the client with the GUID, then computes the SHA1 hash -// and returns it as a based64 encoded string. -func wsAcceptKey(key string) string { - h := sha1.New() - h.Write([]byte(key)) - h.Write(wsGUID) - return base64.StdEncoding.EncodeToString(h.Sum(nil)) -} diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket_go126.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket_go126.go deleted file mode 100644 index d6f38634e..000000000 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats-server/v2/server/websocket_go126.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2026 The NATS Authors -// 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. - -//go:build go1.26 - -package server - -import ( - "crypto/fips140" - "crypto/sha1" - "encoding/base64" -) - -func wsAllowedFIPS() bool { - // As SHA-1 is only used for Sec-WebSocket-Key and Sec-WebSocket-Accept, we - // can continue to allow it in FIPS builds as long as they are built with - // Go 1.26 or later only. - return true -} - -// Concatenate the key sent by the client with the GUID, then computes the SHA1 hash -// and returns it as a based64 encoded string. -func wsAcceptKey(key string) string { - var r []byte - fips140.WithoutEnforcement(func() { - h := sha1.New() - h.Write([]byte(key)) - h.Write(wsGUID) - r = h.Sum(nil) - }) - return base64.StdEncoding.EncodeToString(r) -} diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/README.md b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/README.md index dd47aa422..37413ecdc 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/README.md +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/README.md @@ -7,8 +7,8 @@ A [Go](http://golang.org) client for the [NATS messaging system](https://nats.io [License-Image]: https://img.shields.io/badge/License-Apache2-blue.svg [ReportCard-Url]: https://goreportcard.com/report/github.com/nats-io/nats.go [ReportCard-Image]: https://goreportcard.com/badge/github.com/nats-io/nats.go -[Build-Status-Url]: https://github.com/nats-io/nats.go/actions/workflows/ci.yaml?query=event%3Arelease -[Build-Status-Image]: https://github.com/nats-io/nats.go/actions/workflows/ci.yaml/badge.svg?event=release +[Build-Status-Url]: https://github.com/nats-io/nats.go/actions +[Build-Status-Image]: https://github.com/nats-io/nats.go/actions/workflows/ci.yaml/badge.svg?branch=main [GoDoc-Url]: https://pkg.go.dev/github.com/nats-io/nats.go [GoDoc-Image]: https://img.shields.io/badge/GoDoc-reference-007d9c [Coverage-Url]: https://coveralls.io/r/nats-io/nats.go?branch=main @@ -23,7 +23,7 @@ A [Go](http://golang.org) client for the [NATS messaging system](https://nats.io go get github.com/nats-io/nats.go@latest # To get a specific version: -go get github.com/nats-io/nats.go@v1.52.0 +go get github.com/nats-io/nats.go@v1.51.0 # Note that the latest major version for NATS Server is v2: go get github.com/nats-io/nats-server/v2@latest diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/go_test.mod b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/go_test.mod index 6a1e42660..80e6c7daf 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/go_test.mod +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/go_test.mod @@ -6,17 +6,17 @@ require ( github.com/golang/protobuf v1.5.4 github.com/klauspost/compress v1.18.5 github.com/nats-io/jwt/v2 v2.8.1 - github.com/nats-io/nats-server/v2 v2.14.0 + github.com/nats-io/nats-server/v2 v2.12.6 github.com/nats-io/nkeys v0.4.15 github.com/nats-io/nuid v1.0.1 google.golang.org/protobuf v1.33.0 ) require ( - github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op // indirect + github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op // indirect github.com/google/go-tpm v0.9.8 // indirect - github.com/minio/highwayhash v1.0.4 // indirect - golang.org/x/crypto v0.50.0 // indirect - golang.org/x/sys v0.43.0 // indirect + github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 // indirect + golang.org/x/crypto v0.49.0 // indirect + golang.org/x/sys v0.42.0 // indirect golang.org/x/time v0.15.0 // indirect ) diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/go_test.sum b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/go_test.sum index 58effba4b..10127110d 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/go_test.sum +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/go_test.sum @@ -1,29 +1,47 @@ -github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= -github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= +github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op h1:kpBdlEPbRvff0mDD1gk7o9BhI16b9p5yYAXRlidpqJE= +github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +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= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= -github.com/minio/highwayhash v1.0.4 h1:asJizugGgchQod2ja9NJlGOWq4s7KsAWr5XUc9Clgl4= -github.com/minio/highwayhash v1.0.4/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= +github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk= +github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/nats-io/jwt/v2 v2.8.1 h1:V0xpGuD/N8Mi+fQNDynXohVvp7ZztevW5io8CUWlPmU= github.com/nats-io/jwt/v2 v2.8.1/go.mod h1:nWnOEEiVMiKHQpnAy4eXlizVEtSfzacZ1Q43LIRavZg= -github.com/nats-io/nats-server/v2 v2.14.0 h1:+8q0HrDFotwLLcGH/legOEOnowunhK+aZ4GYBIWpQlM= -github.com/nats-io/nats-server/v2 v2.14.0/go.mod h1:ImVUUDvfClJbb6cuJQRc1VmgDCXKM5ds0OoiG9MVOKo= +github.com/nats-io/nats-server/v2 v2.12.6 h1:Egbx9Vl7Ch8wTtpXPGqbehkZ+IncKqShUxvrt1+Enc8= +github.com/nats-io/nats-server/v2 v2.12.6/go.mod h1:4HPlrvtmSO3yd7KcElDNMx9kv5EBJBnJJzQPptXlheo= github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4= github.com/nats-io/nkeys v0.4.15/go.mod h1:CpMchTXC9fxA5zrMo4KpySxNjiDVvr8ANOSZdiNfUrs= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= +golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/nats.go b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/nats.go index d2d338d46..495f9edb0 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/nats.go +++ b/src/code.cloudfoundry.org/vendor/github.com/nats-io/nats.go/nats.go @@ -49,7 +49,7 @@ import ( // Default Constants const ( - Version = "1.52.0" + Version = "1.51.0" DefaultURL = "nats://127.0.0.1:4222" DefaultPort = 4222 DefaultMaxReconnect = 60 @@ -5100,15 +5100,6 @@ func (s *Subscription) StatusChanged(statuses ...SubStatus) <-chan SubStatus { ch := make(chan SubStatus, 10) s.mu.Lock() defer s.mu.Unlock() - - if s.status == SubscriptionClosed { - if slices.Contains(statuses, SubscriptionClosed) { - ch <- SubscriptionClosed - } - close(ch) - return ch - } - for _, status := range statuses { s.registerStatusChangeListener(status, ch) // initial status diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/.gitignore b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/.gitignore index c9f054620..6faaaf315 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/.gitignore +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/.gitignore @@ -1,7 +1,6 @@ .DS_Store TODO tmp/**/* -integration/tmp_*/ *.coverprofile .vscode .idea/ diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md index 224e8db5f..d382b0640 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md @@ -1,9 +1,3 @@ -## 2.29.0 - -`GinkgoHelperGo` makes it easier to write test helpers that need to run in goroutines. Specifically, it makes managing the failure state and capturing failure panics correctly straightforward. - -`ginkgo outline` now includes entries defined in `DescribeTableSubtree` - ## 2.28.3 ### Maintenance diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go index c380bbf21..5d8d00bb1 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go @@ -163,17 +163,17 @@ func ginkgoNodeFromCallExpr(fset *token.FileSet, ce *ast.CallExpr, ginkgoPackage n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) n.Labels = labelFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName - case "Context", "Describe", "When", "DescribeTable", "DescribeTableSubtree": + case "Context", "Describe", "When", "DescribeTable": n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) n.Labels = labelFromCallExpr(ce) n.Pending = pendingFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName - case "FContext", "FDescribe", "FWhen", "FDescribeTable", "FDescribeTableSubtree": + case "FContext", "FDescribe", "FWhen", "FDescribeTable": n.Focused = true n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) n.Labels = labelFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName - case "PContext", "PDescribe", "PWhen", "XContext", "XDescribe", "XWhen", "PDescribeTable", "XDescribeTable", "PDescribeTableSubtree", "XDescribeTableSubtree": + case "PContext", "PDescribe", "PWhen", "XContext", "XDescribe", "XWhen", "PDescribeTable", "XDescribeTable": n.Pending = true n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) n.Labels = labelFromCallExpr(ce) diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go index 206043f1d..e99d557d1 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go @@ -54,7 +54,6 @@ func FromASTFile(fset *token.FileSet, src *ast.File) (*outline, error) { // Node is not a Ginkgo spec or container, so it was not pushed onto the stack, continue return true } - expandSubtree(lastVisitedGinkgoNode) stack = stack[0 : len(stack)-1] return true }) @@ -129,29 +128,3 @@ func (o *outline) StringIndent(width int) string { return b.String() } - -// expandSubtree restructures a DescribeTableSubtree node so that each Entry -// child gets a copy of the subtree's spec nodes as its children. This mirrors -// the runtime behavior where each Entry generates a container with the specs -// defined in the DescribeTableSubtree body. -func expandSubtree(gn *ginkgoNode) { - if !strings.Contains(gn.Name, "DescribeTableSubtree") { - return - } - subNodes, entries := splitSubtreeSubnodes(gn.Nodes) - gn.Nodes = entries - for _, entry := range entries { - entry.Nodes = subNodes - } -} - -// splitSubtreeSubnodes splits the child nodes of a DescribeTableSubtree into -// spec/container nodes (defined in the body) and Entry nodes. -func splitSubtreeSubnodes(nodes []*ginkgoNode) ([]*ginkgoNode, []*ginkgoNode) { - for i, node := range nodes { - if strings.Contains(node.Name, "Entry") { - return nodes[:i], nodes[i:] - } - } - return nodes, nil -} diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/helpergo_dsl.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/helpergo_dsl.go deleted file mode 100644 index 9d04cc845..000000000 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/helpergo_dsl.go +++ /dev/null @@ -1,143 +0,0 @@ -package ginkgo - -import ( - "github.com/onsi/ginkgo/v2/internal/global" - ginkgotypes "github.com/onsi/ginkgo/v2/types" -) - -// GinkgoHelperGo synchronously calls the specified “helper” function in a new -// go routine and with a “defer GinkgoRecover()” already in place, passing the -// function a “helper Fail”. GinkgoHelperGo is typically called from custom test -// helpers that in turn need to synchronously execute caller-supplied custom -// test code in a new Go routine while waiting for this new Go routine to -// terminate (either successfully or failing). -// -// GinkgoHelperGo hides the non-trivial details of correctly unblocking the -// caller's waiting go routine as well as reporting the correct call sites, -// depending on whether the test helper failed, or the caller-supplied function -// had its assertions failing or panicked. -// -// Let's take the following example of a test helper named “EnsureSprockets” -// that runs a set of caller-supplied assertions synchronously on a new Go -// routine and waits for the outcome before returning to the caller of the test -// helper. This is just using Ginkgo: -// -// func EnsureSprockets(sprockets int, assertions func()) { -// GinkgoHelper() -// GinkgoHelperGo(func(helperFail func(string, ...int)) { -// if sprockets == 0 { -// helperFail("sprockets must not be zero") -// } -// assertions() -// }) -// } -// -// And now for an example that additionally uses Gomega assertions. -// -// func EnsureSprockets(sprockets int, assertions func()) { -// GinkgoHelper() -// GinkgoHelperGo(func(helperFail func(string, ...int)) { -// g := gomega.NewGomega(helperFail) -// g.Expect(sprockets).Not(BeZero()) -// assertions() -// }) -// } -// -// The called helper function should make any custom helper-related assertions -// using the passed “helper Fail”. Gomega users will want to create a new Gomega -// wired into this helper Fail. It is expected for the helper function at some -// point to call into a user-supplied function that might contain its own -// assertions. In the example above, that would be the function passed as -// assertions. -// -// Any failing assertion using the helper Gomega in the helper function will be -// reported as a fail at the call site of GinkgoHelperGo. Preferably, only -// custom test helpers call GinkgoHelperGo and thus mark themselves as -// [GinkgoHelper] also: in this case, the fail will be shown at the call site of -// the custom test helper. -// -// Any other failing assertions inside the caller-supplied custom test code and -// thus inside the helper function will instead be reported at the location of -// the failed assertion. -// -// If the caller-supplied custom test code panics, GinkgoHelperGo will fail at -// its call site, or at the call site of the custom test helper if it uses -// GinkgoHelper, reporting the usual stack trace for the panic, as a plain -// GinkgoRecover would also do. -// -// Important: the Gomega passed to the called function must only be used in -// assertions belonging to the test helper, but not any user test code called -// from the test helper. Thus, do not pass the Gomega passed to the helper -// function further on to any user test code functions. -func GinkgoHelperGo(fn func(fail func(message string, callerSkip ...int))) { - // userPanicked signals that the called user code panicked, such as due to a - // failed Gomega assertion. - type userPanicked struct{} - - // helperPanicked signals that some helper code assertion panicked in the - // separate Go routine and we are expected to Fail the current test with that - // reason, but on the caller's Go routine. - type helperPanicked string - - GinkgoHelper() - - // possible types of values sent over the result channel: - // - nil (untyped): no problem at all, proceed. - // - helperPanicked: the message with which to (re)fail in the caller's - // go routine. - // - userPanicked: indication to (also) fail on the caller's go routine; - // the message doesn't matter as the user code fail takes precedence. - ch := make(chan any) - - go func() { - isHelperPanic := false - helperFail := func(message string, callerSkip ...int) { - isHelperPanic = true - Fail(message, callerSkip...) - } - // Please note that we cannot simply recover a helper panic before - // GinkgoRecover kicks in as then GinkgoRecover would always report the - // stack trace only from the place of rethrown panic ... and that's - // pretty useless, because it would just consist of the panic rethrow. - defer func() { - // We need to unblock and immediately fail the waiting caller's - // go routine either for a reason, or just "because" when - // GinkgoRecover has already failed the current test on the - // separate go routine. - if global.Failer.GetState() != ginkgotypes.SpecStatePassed { - if isHelperPanic { - _, failure := global.Failer.Drain() - ch <- helperPanicked(failure.Message) - } else { - // keep the panic failure already recorded by GinkgoRecover. - ch <- userPanicked{} - } - } - close(ch) // causes a nil in case there were no panics anywhere. - }() - // Nota bene: GinkgoRecover always eats any user panic and channel the - // panic value into Ginkgo's Failer.Panic(). We can peek at the last - // failure recorded, which should be nil if GinkgoRecover didn't swallow - // a user code panic. The "problem" with GinkgoRecover is that it turns - // any panic value into a string message, so we loose any specific - // typing. - defer GinkgoRecover() - - fn(helperFail) - }() - - // Did we run into trouble? - switch v := (<-ch).(type) { - case userPanicked: - // The message actually is irrelevant, as it comes only second to - // the already registered user panic message. We just need Fail to - // panic on the caller's go routine in order to unblock the test. - Fail("fn panicked", 1) - case helperPanicked: - // Report the failure on the new go routine instead on the caller's go - // routine. - Fail(string(v), 1) - default: - // It's all fine! - } -} diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/types/version.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/types/version.go index 003604bd8..4479578f9 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/types/version.go +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/ginkgo/v2/types/version.go @@ -1,3 +1,3 @@ package types -const VERSION = "2.29.0" +const VERSION = "2.28.3" diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/CHANGELOG.md b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/CHANGELOG.md index 5f9966fbe..9c94d0e6c 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/CHANGELOG.md +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/CHANGELOG.md @@ -1,13 +1,3 @@ -## 1.41.0 - -### Features - -Add `BeASlice` and `BeAnArray` matchers - -### Fixes - -Object formatting now detects pointer cycles to avoid runaway formatting output. - ## 1.40.0 We're adopting a new release strategy to minimize dependency bloat in projects that consume Gomega. It is a limitation of the go mod toolchain that _test_ subdependencies of your project's direct dependencies get pulled in as *indirect* dependencies. In the case of Gomega, this ends up pulling in all of Ginkgo into your `go.mod` even if you are only using Gomega (Gomega uses Ginkgo for its own tests). diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/format/format.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/format/format.go index d56f9a475..6c23ba338 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/format/format.go +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/format/format.go @@ -262,7 +262,7 @@ func Object(object any, indentation uint) string { if err, ok := object.(error); ok && !isNilValue(value) { // isNilValue check needed here to avoid nil deref due to boxed nil commonRepresentation += "\n" + IndentString(err.Error(), indentation) + "\n" + indent } - return fmt.Sprintf("%s<%s>: %s%s", indent, formatType(value), commonRepresentation, formatValue(value, indentation, true, map[uintptr]struct{}{})) + return fmt.Sprintf("%s<%s>: %s%s", indent, formatType(value), commonRepresentation, formatValue(value, indentation, true)) } /* @@ -306,7 +306,7 @@ func formatType(v reflect.Value) string { } } -func formatValue(value reflect.Value, indentation uint, isTopLevel bool, visited map[uintptr]struct{}) string { +func formatValue(value reflect.Value, indentation uint, isTopLevel bool) string { if indentation > MaxDepth { return "..." } @@ -367,28 +367,23 @@ func formatValue(value reflect.Value, indentation uint, isTopLevel bool, visited case reflect.Func: return fmt.Sprintf("0x%x", value.Pointer()) case reflect.Ptr: - ptr := value.Pointer() - if _, ok := visited[ptr]; ok { - return fmt.Sprintf("0x%x (cyclic reference)", ptr) - } - visited[ptr] = struct{}{} - return formatValue(value.Elem(), indentation, isTopLevel, visited) + return formatValue(value.Elem(), indentation, isTopLevel) case reflect.Slice: - return truncateLongStrings(formatSlice(value, indentation, visited)) + return truncateLongStrings(formatSlice(value, indentation)) case reflect.String: return truncateLongStrings(formatString(value.String(), indentation, isTopLevel)) case reflect.Array: - return truncateLongStrings(formatSlice(value, indentation, visited)) + return truncateLongStrings(formatSlice(value, indentation)) case reflect.Map: - return truncateLongStrings(formatMap(value, indentation, visited)) + return truncateLongStrings(formatMap(value, indentation)) case reflect.Struct: if value.Type() == timeType && value.CanInterface() { t, _ := value.Interface().(time.Time) return t.Format(time.RFC3339Nano) } - return truncateLongStrings(formatStruct(value, indentation, visited)) + return truncateLongStrings(formatStruct(value, indentation)) case reflect.Interface: - return formatInterface(value, indentation, visited) + return formatInterface(value, indentation) default: if value.CanInterface() { return truncateLongStrings(fmt.Sprintf("%#v", value.Interface())) @@ -419,7 +414,7 @@ func formatString(object any, indentation uint, isTopLevel bool) string { } } -func formatSlice(v reflect.Value, indentation uint, visited map[uintptr]struct{}) string { +func formatSlice(v reflect.Value, indentation uint) string { if v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Uint8 && isPrintableString(string(v.Bytes())) { return formatString(v.Bytes(), indentation, false) } @@ -428,7 +423,7 @@ func formatSlice(v reflect.Value, indentation uint, visited map[uintptr]struct{} result := make([]string, l) longest := 0 for i := range l { - result[i] = formatValue(v.Index(i), indentation+1, false, visited) + result[i] = formatValue(v.Index(i), indentation+1, false) if len(result[i]) > longest { longest = len(result[i]) } @@ -441,14 +436,14 @@ func formatSlice(v reflect.Value, indentation uint, visited map[uintptr]struct{} return fmt.Sprintf("[%s]", strings.Join(result, ", ")) } -func formatMap(v reflect.Value, indentation uint, visited map[uintptr]struct{}) string { +func formatMap(v reflect.Value, indentation uint) string { l := v.Len() result := make([]string, l) longest := 0 for i, key := range v.MapKeys() { value := v.MapIndex(key) - result[i] = fmt.Sprintf("%s: %s", formatValue(key, indentation+1, false, visited), formatValue(value, indentation+1, false, visited)) + result[i] = fmt.Sprintf("%s: %s", formatValue(key, indentation+1, false), formatValue(value, indentation+1, false)) if len(result[i]) > longest { longest = len(result[i]) } @@ -461,7 +456,7 @@ func formatMap(v reflect.Value, indentation uint, visited map[uintptr]struct{}) return fmt.Sprintf("{%s}", strings.Join(result, ", ")) } -func formatStruct(v reflect.Value, indentation uint, visited map[uintptr]struct{}) string { +func formatStruct(v reflect.Value, indentation uint) string { t := v.Type() l := v.NumField() @@ -470,7 +465,7 @@ func formatStruct(v reflect.Value, indentation uint, visited map[uintptr]struct{ for i := range l { structField := t.Field(i) fieldEntry := v.Field(i) - representation := fmt.Sprintf("%s: %s", structField.Name, formatValue(fieldEntry, indentation+1, false, visited)) + representation := fmt.Sprintf("%s: %s", structField.Name, formatValue(fieldEntry, indentation+1, false)) result = append(result, representation) if len(representation) > longest { longest = len(representation) @@ -483,8 +478,8 @@ func formatStruct(v reflect.Value, indentation uint, visited map[uintptr]struct{ return fmt.Sprintf("{%s}", strings.Join(result, ", ")) } -func formatInterface(v reflect.Value, indentation uint, visited map[uintptr]struct{}) string { - return fmt.Sprintf("<%s>%s", formatType(v.Elem()), formatValue(v.Elem(), indentation, false, visited)) +func formatInterface(v reflect.Value, indentation uint) string { + return fmt.Sprintf("<%s>%s", formatType(v.Elem()), formatValue(v.Elem(), indentation, false)) } func isNilValue(a reflect.Value) bool { diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/gomega_dsl.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/gomega_dsl.go index df16ede11..af1341bdb 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/gomega_dsl.go +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/gomega_dsl.go @@ -22,7 +22,7 @@ import ( "github.com/onsi/gomega/types" ) -const GOMEGA_VERSION = "1.41.0" +const GOMEGA_VERSION = "1.40.0" const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler. If you're using Ginkgo then you probably forgot to put your assertion in an It(). diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers.go index bf5722605..16ca8f46d 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers.go +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers.go @@ -621,18 +621,6 @@ func BeADirectory() types.GomegaMatcher { return &matchers.BeADirectoryMatcher{} } -// BeASlice succeeds if actual is a value of slice type. -// This is useful when actual has type any (interface{}) and you want to assert it is a slice. -func BeASlice() types.GomegaMatcher { - return &matchers.BeASliceMatcher{} -} - -// BeAnArray succeeds if actual is a value of array type. -// This is useful when actual has type any (interface{}) and you want to assert it is an array. -func BeAnArray() types.GomegaMatcher { - return &matchers.BeAnArrayMatcher{} -} - // HaveHTTPStatus succeeds if the Status or StatusCode field of an HTTP response matches. // Actual must be either a *http.Response or *httptest.ResponseRecorder. // Expected must be either an int or a string. diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers/be_a_slice_matcher.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers/be_a_slice_matcher.go deleted file mode 100644 index 4fcad5127..000000000 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers/be_a_slice_matcher.go +++ /dev/null @@ -1,28 +0,0 @@ -// untested sections: 1 - -package matchers - -import ( - "fmt" - "reflect" - - "github.com/onsi/gomega/format" -) - -type BeASliceMatcher struct { -} - -func (matcher *BeASliceMatcher) Match(actual any) (success bool, err error) { - if actual == nil { - return false, fmt.Errorf("BeASlice matcher expects a value, got nil") - } - return reflect.TypeOf(actual).Kind() == reflect.Slice, nil -} - -func (matcher *BeASliceMatcher) FailureMessage(actual any) (message string) { - return format.Message(actual, "to be a slice") -} - -func (matcher *BeASliceMatcher) NegatedFailureMessage(actual any) (message string) { - return format.Message(actual, "not to be a slice") -} diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers/be_an_array_matcher.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers/be_an_array_matcher.go deleted file mode 100644 index 573aa8198..000000000 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/matchers/be_an_array_matcher.go +++ /dev/null @@ -1,28 +0,0 @@ -// untested sections: 1 - -package matchers - -import ( - "fmt" - "reflect" - - "github.com/onsi/gomega/format" -) - -type BeAnArrayMatcher struct { -} - -func (matcher *BeAnArrayMatcher) Match(actual any) (success bool, err error) { - if actual == nil { - return false, fmt.Errorf("BeAnArray matcher expects a value, got nil") - } - return reflect.TypeOf(actual).Kind() == reflect.Array, nil -} - -func (matcher *BeAnArrayMatcher) FailureMessage(actual any) (message string) { - return format.Message(actual, "to be an array") -} - -func (matcher *BeAnArrayMatcher) NegatedFailureMessage(actual any) (message string) { - return format.Message(actual, "not to be an array") -} diff --git a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/types/types.go b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/types/types.go index e444451ac..685a46f37 100644 --- a/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/types/types.go +++ b/src/code.cloudfoundry.org/vendor/github.com/onsi/gomega/types/types.go @@ -66,12 +66,6 @@ func MatchMayChangeInTheFuture(matcher GomegaMatcher, value any) bool { // AsyncAssertions are returned by Eventually and Consistently and enable matchers to be polled repeatedly to ensure // they are eventually satisfied -// -// The optional optionalDescription argument allows you to annotate the assertion with additional information. -// It is passed as the second argument and can be a format string followed by arguments, or a func() string. -// The description is included in failure messages to provide context. -// -// For details on annotating assertions, see: https://onsi.github.io/gomega/#annotating-assertions type AsyncAssertion interface { Should(matcher GomegaMatcher, optionalDescription ...any) bool ShouldNot(matcher GomegaMatcher, optionalDescription ...any) bool @@ -92,12 +86,6 @@ type AsyncAssertion interface { } // Assertions are returned by Ω and Expect and enable assertions against Gomega matchers -// -// The optional optionalDescription argument allows you to annotate the assertion with additional information. -// It is passed as the second argument and can be a format string followed by arguments, or a func() string. -// The description is included in failure messages to provide context. -// -// For details on annotating assertions, see: https://onsi.github.io/gomega/#annotating-assertions type Assertion interface { Should(matcher GomegaMatcher, optionalDescription ...any) bool ShouldNot(matcher GomegaMatcher, optionalDescription ...any) bool diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/blake2b/go125.go b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/blake2b/go125.go new file mode 100644 index 000000000..67e990b7e --- /dev/null +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/blake2b/go125.go @@ -0,0 +1,11 @@ +// Copyright 2025 The Go 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 go1.25 + +package blake2b + +import "hash" + +var _ hash.XOF = (*xof)(nil) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go index bfe546b60..b850e772e 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.go @@ -20,7 +20,7 @@ func chacha20Poly1305Open(dst []byte, key []uint32, src, ad []byte) bool func chacha20Poly1305Seal(dst []byte, key []uint32, src, ad []byte) var ( - useAVX2 = cpu.X86.HasSSSE3 && cpu.X86.HasAVX2 && cpu.X86.HasBMI2 + useAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasBMI2 ) // setupState writes a ChaCha20 input matrix to state. See @@ -47,7 +47,7 @@ func setupState(state *[16]uint32, key *[32]byte, nonce []byte) { } func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) []byte { - if !useAVX2 { + if !cpu.X86.HasSSSE3 { return c.sealGeneric(dst, nonce, plaintext, additionalData) } @@ -66,7 +66,7 @@ func (c *chacha20poly1305) seal(dst, nonce, plaintext, additionalData []byte) [] } func (c *chacha20poly1305) open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) { - if !useAVX2 { + if !cpu.X86.HasSSSE3 { return c.openGeneric(dst, nonce, ciphertext, additionalData) } diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s index c703c1347..fd5ee845f 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/chacha20poly1305/chacha20poly1305_amd64.s @@ -6,6 +6,27 @@ // func polyHashADInternal<>() TEXT polyHashADInternal<>(SB), NOSPLIT, $0 + // Hack: Must declare #define macros inside of a function due to Avo constraints + // ROL rotates the uint32s in register R left by N bits, using temporary T. + #define ROL(N, R, T) \ + MOVO R, T; \ + PSLLL $(N), T; \ + PSRLL $(32-(N)), R; \ + PXOR T, R + + // ROL8 rotates the uint32s in register R left by 8, using temporary T if needed. + #ifdef GOAMD64_v2 + #define ROL8(R, T) PSHUFB ·rol8<>(SB), R + #else + #define ROL8(R, T) ROL(8, R, T) + #endif + + // ROL16 rotates the uint32s in register R left by 16, using temporary T if needed. + #ifdef GOAMD64_v2 + #define ROL16(R, T) PSHUFB ·rol16<>(SB), R + #else + #define ROL16(R, T) ROL(16, R, T) + #endif XORQ R10, R10 XORQ R11, R11 XORQ R12, R12 @@ -171,113 +192,423 @@ hashADDone: // Requires: AVX, AVX2, BMI2, CMOV, SSE2 TEXT ·chacha20Poly1305Open(SB), $288-97 // For aligned stack access - MOVQ SP, BP - ADDQ $0x20, BP - ANDQ $-32, BP - MOVQ dst_base+0(FP), DI - MOVQ key_base+24(FP), R8 - MOVQ src_base+48(FP), SI - MOVQ src_len+56(FP), BX - MOVQ ad_base+72(FP), CX - VZEROUPPER - VMOVDQU ·chacha20Constants<>+0(SB), Y0 - VBROADCASTI128 16(R8), Y14 - VBROADCASTI128 32(R8), Y12 - VBROADCASTI128 48(R8), Y4 - VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 + MOVQ SP, BP + ADDQ $0x20, BP + ANDQ $-32, BP + MOVQ dst_base+0(FP), DI + MOVQ key_base+24(FP), R8 + MOVQ src_base+48(FP), SI + MOVQ src_len+56(FP), BX + MOVQ ad_base+72(FP), CX + + // Check for AVX2 support + CMPB ·useAVX2+0(SB), $0x01 + JE chacha20Poly1305Open_AVX2 // Special optimization, for very short buffers - CMPQ BX, $0xc0 - JBE openAVX2192 - CMPQ BX, $0x00000140 - JBE openAVX2320 - - // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream - VMOVDQA Y14, 32(BP) - VMOVDQA Y12, 64(BP) - VMOVDQA Y4, 192(BP) - MOVQ $0x0000000a, R9 - -openAVX2PreparePolyKey: - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x0c, Y14, Y3 - VPSRLD $0x14, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x07, Y14, Y3 - VPSRLD $0x19, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPALIGNR $0x04, Y14, Y14, Y14 - VPALIGNR $0x08, Y12, Y12, Y12 - VPALIGNR $0x0c, Y4, Y4, Y4 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x0c, Y14, Y3 - VPSRLD $0x14, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x07, Y14, Y3 - VPSRLD $0x19, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPALIGNR $0x0c, Y14, Y14, Y14 - VPALIGNR $0x08, Y12, Y12, Y12 - VPALIGNR $0x04, Y4, Y4, Y4 - DECQ R9 - JNE openAVX2PreparePolyKey - VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 - VPADDD 32(BP), Y14, Y14 - VPADDD 64(BP), Y12, Y12 - VPADDD 192(BP), Y4, Y4 - VPERM2I128 $0x02, Y0, Y14, Y3 + CMPQ BX, $0x80 + JBE openSSE128 + + // For long buffers, prepare the poly key first + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X9, X13 + + // Store state on stack for future use + MOVO X3, 32(BP) + MOVO X6, 48(BP) + MOVO X9, 128(BP) + MOVQ $0x0000000a, R9 + +openSSEPreparePolyKey: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + DECQ R9 + JNE openSSEPreparePolyKey - // Clamp and store poly key - VPAND ·polyClampMask<>+0(SB), Y3, Y3 - VMOVDQA Y3, (BP) + // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL 32(BP), X3 - // Stream for the first 64 bytes - VPERM2I128 $0x13, Y0, Y14, Y0 - VPERM2I128 $0x13, Y12, Y4, Y14 + // Clamp and store the key + PAND ·polyClampMask<>+0(SB), X0 + MOVO X0, (BP) + MOVO X3, 16(BP) - // Hash AD + first 64 bytes + // Hash AAD MOVQ ad_len+80(FP), R9 CALL polyHashADInternal<>(SB) - XORQ CX, CX -openAVX2InitialHash64: - ADDQ (SI)(CX*1), R10 - ADCQ 8(SI)(CX*1), R11 +openSSEMainLoop: + CMPQ BX, $0x00000100 + JB openSSEMainLoopDone + + // Load state, increment counter blocks + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 + + // Store counters + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + + // There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we hash + // 2 blocks, and for the remaining 4 only 1 block - for a total of 16 + MOVQ $0x00000004, CX + MOVQ SI, R9 + +openSSEInternalLoop: + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + ADDQ (R9), R10 + ADCQ 8(R9), R11 ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 IMULQ R12, R15 - MULXQ R11, AX, DX ADDQ AX, R14 ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 ADDQ AX, R15 + ADCQ $0x00, DX + LEAQ 16(R9), R9 + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + IMULQ R12, R8 + ADDQ R10, R15 ADCQ DX, R8 + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 MOVQ R13, R10 MOVQ R14, R11 MOVQ R15, R12 @@ -293,494 +624,3069 @@ openAVX2InitialHash64: ADDQ R15, R10 ADCQ R8, R11 ADCQ $0x00, R12 - ADDQ $0x10, CX - CMPQ CX, $0x40 - JNE openAVX2InitialHash64 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ CX + JGE openSSEInternalLoop + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(R9), R9 + CMPQ CX, $-6 + JG openSSEInternalLoop + + // Add in the state + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + + // Load - xor - store + MOVO X15, 64(BP) + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU X0, (DI) + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU X3, 16(DI) + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU X6, 32(DI) + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X9, 48(DI) + MOVOU 64(SI), X9 + PXOR X9, X1 + MOVOU X1, 64(DI) + MOVOU 80(SI), X9 + PXOR X9, X4 + MOVOU X4, 80(DI) + MOVOU 96(SI), X9 + PXOR X9, X7 + MOVOU X7, 96(DI) + MOVOU 112(SI), X9 + PXOR X9, X10 + MOVOU X10, 112(DI) + MOVOU 128(SI), X9 + PXOR X9, X2 + MOVOU X2, 128(DI) + MOVOU 144(SI), X9 + PXOR X9, X5 + MOVOU X5, 144(DI) + MOVOU 160(SI), X9 + PXOR X9, X8 + MOVOU X8, 160(DI) + MOVOU 176(SI), X9 + PXOR X9, X11 + MOVOU X11, 176(DI) + MOVOU 192(SI), X9 + PXOR X9, X12 + MOVOU X12, 192(DI) + MOVOU 208(SI), X9 + PXOR X9, X13 + MOVOU X13, 208(DI) + MOVOU 224(SI), X9 + PXOR X9, X14 + MOVOU X14, 224(DI) + MOVOU 240(SI), X9 + PXOR 64(BP), X9 + MOVOU X9, 240(DI) + LEAQ 256(SI), SI + LEAQ 256(DI), DI + SUBQ $0x00000100, BX + JMP openSSEMainLoop + +openSSEMainLoopDone: + // Handle the various tail sizes efficiently + TESTQ BX, BX + JE openSSEFinalize + CMPQ BX, $0x40 + JBE openSSETail64 + CMPQ BX, $0x80 + JBE openSSETail128 + CMPQ BX, $0xc0 + JBE openSSETail192 + JMP openSSETail256 - // Decrypt the first 64 bytes - VPXOR (SI), Y0, Y0 - VPXOR 32(SI), Y14, Y14 - VMOVDQU Y0, (DI) - VMOVDQU Y14, 32(DI) - LEAQ 64(SI), SI - LEAQ 64(DI), DI - SUBQ $0x40, BX +openSSEFinalize: + // Hash in the PT, AAD lengths + ADDQ ad_len+80(FP), R10 + ADCQ src_len+56(FP), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 -openAVX2MainLoop: - CMPQ BX, $0x00000200 - JB openAVX2MainLoopDone + // Final reduce + MOVQ R10, R13 + MOVQ R11, R14 + MOVQ R12, R15 + SUBQ $-5, R10 + SBBQ $-1, R11 + SBBQ $0x03, R12 + CMOVQCS R13, R10 + CMOVQCS R14, R11 + CMOVQCS R15, R12 - // Load state, increment counter blocks, store the incremented counters - VMOVDQU ·chacha20Constants<>+0(SB), Y0 - VMOVDQA Y0, Y5 - VMOVDQA Y0, Y6 - VMOVDQA Y0, Y7 - VMOVDQA 32(BP), Y14 - VMOVDQA Y14, Y9 - VMOVDQA Y14, Y10 - VMOVDQA Y14, Y11 - VMOVDQA 64(BP), Y12 - VMOVDQA Y12, Y13 - VMOVDQA Y12, Y8 - VMOVDQA Y12, Y15 - VMOVDQA 192(BP), Y4 - VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 - VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 - VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 - VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 - VMOVDQA Y4, 96(BP) - VMOVDQA Y1, 128(BP) - VMOVDQA Y2, 160(BP) - VMOVDQA Y3, 192(BP) - XORQ CX, CX + // Add in the "s" part of the key + ADDQ 16(BP), R10 + ADCQ 24(BP), R11 -openAVX2InternalLoop: - ADDQ (SI)(CX*1), R10 - ADCQ 8(SI)(CX*1), R11 - ADCQ $0x01, R12 - VPADDD Y14, Y0, Y0 - VPADDD Y9, Y5, Y5 - VPADDD Y10, Y6, Y6 - VPADDD Y11, Y7, Y7 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 - IMULQ R12, R15 - MULXQ R11, AX, DX - ADDQ AX, R14 + // Finally, constant time compare to the tag at the end of the message + XORQ AX, AX + MOVQ $0x00000001, DX + XORQ (SI), R10 + XORQ 8(SI), R11 + ORQ R11, R10 + CMOVQEQ DX, AX + + // Return true iff tags are equal + MOVB AX, ret+96(FP) + RET + +openSSE128: + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X3, X13 + MOVO X6, X14 + MOVO X10, X15 + MOVQ $0x0000000a, R9 + +openSSE128InnerCipherLoop: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ R9 + JNE openSSE128InnerCipherLoop + + // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL X13, X3 + PADDL X13, X4 + PADDL X13, X5 + PADDL X14, X7 + PADDL X14, X8 + PADDL X15, X10 + PADDL ·sseIncMask<>+0(SB), X15 + PADDL X15, X11 + + // Clamp and store the key + PAND ·polyClampMask<>+0(SB), X0 + MOVOU X0, (BP) + MOVOU X3, 16(BP) + + // Hash + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + +openSSE128Open: + CMPQ BX, $0x10 + JB openSSETail16 + SUBQ $0x10, BX + + // Load for hashing + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + + // Load for decryption + MOVOU (SI), X12 + PXOR X12, X1 + MOVOU X1, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + + // Shift the stream "left" + MOVO X4, X1 + MOVO X7, X4 + MOVO X10, X7 + MOVO X2, X10 + MOVO X5, X2 + MOVO X8, X5 + MOVO X11, X8 + JMP openSSE128Open + +openSSETail16: + TESTQ BX, BX + JE openSSEFinalize + + // We can safely load the CT from the end, because it is padded with the MAC + MOVQ BX, R9 + SHLQ $0x04, R9 + LEAQ ·andMask<>+0(SB), R13 + MOVOU (SI), X12 + ADDQ BX, SI + PAND -16(R13)(R9*1), X12 + MOVO X12, 64(BP) + MOVQ X12, R13 + MOVQ 72(BP), R14 + PXOR X1, X12 + + // We can only store one byte at a time, since plaintext can be shorter than 16 bytes +openSSETail16Store: + MOVQ X12, R8 + MOVB R8, (DI) + PSRLDQ $0x01, X12 + INCQ DI + DECQ BX + JNE openSSETail16Store + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + JMP openSSEFinalize + +openSSETail64: + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + XORQ R9, R9 + MOVQ BX, CX + CMPQ CX, $0x10 + JB openSSETail64LoopB + +openSSETail64LoopA: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + SUBQ $0x10, CX + +openSSETail64LoopB: + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + CMPQ CX, $0x10 + JAE openSSETail64LoopA + CMPQ R9, $0xa0 + JNE openSSETail64LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL 32(BP), X3 + PADDL 48(BP), X6 + PADDL 80(BP), X9 + +openSSETail64DecLoop: + CMPQ BX, $0x10 + JB openSSETail64DecLoopDone + SUBQ $0x10, BX + MOVOU (SI), X12 + PXOR X12, X0 + MOVOU X0, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + MOVO X3, X0 + MOVO X6, X3 + MOVO X9, X6 + JMP openSSETail64DecLoop + +openSSETail64DecLoopDone: + MOVO X0, X1 + JMP openSSETail16 + +openSSETail128: + MOVO ·chacha20Constants<>+0(SB), X1 + MOVO 32(BP), X4 + MOVO 48(BP), X7 + MOVO 128(BP), X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 80(BP) + MOVO X1, X0 + MOVO X4, X3 + MOVO X7, X6 + MOVO X10, X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 96(BP) + XORQ R9, R9 + MOVQ BX, CX + ANDQ $-16, CX + +openSSETail128LoopA: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + +openSSETail128LoopB: + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + CMPQ R9, CX + JB openSSETail128LoopA + CMPQ R9, $0xa0 + JNE openSSETail128LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 96(BP), X9 + PADDL 80(BP), X10 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, (DI) + MOVOU X4, 16(DI) + MOVOU X7, 32(DI) + MOVOU X10, 48(DI) + SUBQ $0x40, BX + LEAQ 64(SI), SI + LEAQ 64(DI), DI + JMP openSSETail64DecLoop + +openSSETail192: + MOVO ·chacha20Constants<>+0(SB), X2 + MOVO 32(BP), X5 + MOVO 48(BP), X8 + MOVO 128(BP), X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X11, 80(BP) + MOVO X2, X1 + MOVO X5, X4 + MOVO X8, X7 + MOVO X11, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + MOVO X1, X0 + MOVO X4, X3 + MOVO X7, X6 + MOVO X10, X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 112(BP) + MOVQ BX, CX + MOVQ $0x000000a0, R9 + CMPQ CX, $0xa0 + CMOVQGT R9, CX + ANDQ $-16, CX + XORQ R9, R9 + +openSSLTail192LoopA: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + +openSSLTail192LoopB: + ADDQ $0x10, R9 + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + CMPQ R9, CX + JB openSSLTail192LoopA + CMPQ R9, $0xa0 + JNE openSSLTail192LoopB + CMPQ BX, $0xb0 + JB openSSLTail192Store + ADDQ 160(SI), R10 + ADCQ 168(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + CMPQ BX, $0xc0 + JB openSSLTail192Store + ADDQ 176(SI), R10 + ADCQ 184(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + +openSSLTail192Store: + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 32(BP), X5 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 48(BP), X8 + PADDL 112(BP), X9 + PADDL 96(BP), X10 + PADDL 80(BP), X11 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X2 + PXOR X13, X5 + PXOR X14, X8 + PXOR X15, X11 + MOVOU X2, (DI) + MOVOU X5, 16(DI) + MOVOU X8, 32(DI) + MOVOU X11, 48(DI) + MOVOU 64(SI), X12 + MOVOU 80(SI), X13 + MOVOU 96(SI), X14 + MOVOU 112(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + SUBQ $0x80, BX + LEAQ 128(SI), SI + LEAQ 128(DI), DI + JMP openSSETail64DecLoop + +openSSETail256: + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 + + // Store counters + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + XORQ R9, R9 + +openSSETail256Loop: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + ADDQ $0x10, R9 + CMPQ R9, $0xa0 + JB openSSETail256Loop + MOVQ BX, CX + ANDQ $-16, CX + +openSSETail256HashLoop: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ $0x10, R9 + CMPQ R9, CX + JB openSSETail256HashLoop + + // Add in the state + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + MOVO X15, 64(BP) + + // Load - xor - store + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVOU 128(SI), X0 + MOVOU 144(SI), X3 + MOVOU 160(SI), X6 + MOVOU 176(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 128(DI) + MOVOU X5, 144(DI) + MOVOU X8, 160(DI) + MOVOU X11, 176(DI) + LEAQ 192(SI), SI + LEAQ 192(DI), DI + SUBQ $0xc0, BX + MOVO X12, X0 + MOVO X13, X3 + MOVO X14, X6 + MOVO 64(BP), X9 + JMP openSSETail64DecLoop + +chacha20Poly1305Open_AVX2: + VZEROUPPER + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x70 + BYTE $0x10 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x20 + BYTE $0xc4 + BYTE $0xc2 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x30 + VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 + + // Special optimization, for very short buffers + CMPQ BX, $0xc0 + JBE openAVX2192 + CMPQ BX, $0x00000140 + JBE openAVX2320 + + // For the general key prepare the key first - as a byproduct we have 64 bytes of cipher stream + VMOVDQA Y14, 32(BP) + VMOVDQA Y12, 64(BP) + VMOVDQA Y4, 192(BP) + MOVQ $0x0000000a, R9 + +openAVX2PreparePolyKey: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x04, Y4, Y4, Y4 + DECQ R9 + JNE openAVX2PreparePolyKey + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD 32(BP), Y14, Y14 + VPADDD 64(BP), Y12, Y12 + VPADDD 192(BP), Y4, Y4 + VPERM2I128 $0x02, Y0, Y14, Y3 + + // Clamp and store poly key + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) + + // Stream for the first 64 bytes + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + + // Hash AD + first 64 bytes + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + XORQ CX, CX + +openAVX2InitialHash64: + ADDQ (SI)(CX*1), R10 + ADCQ 8(SI)(CX*1), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ $0x10, CX + CMPQ CX, $0x40 + JNE openAVX2InitialHash64 + + // Decrypt the first 64 bytes + VPXOR (SI), Y0, Y0 + VPXOR 32(SI), Y14, Y14 + VMOVDQU Y0, (DI) + VMOVDQU Y14, 32(DI) + LEAQ 64(SI), SI + LEAQ 64(DI), DI + SUBQ $0x40, BX + +openAVX2MainLoop: + CMPQ BX, $0x00000200 + JB openAVX2MainLoopDone + + // Load state, increment counter blocks, store the incremented counters + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + XORQ CX, CX + +openAVX2InternalLoop: + ADDQ (SI)(CX*1), R10 + ADCQ 8(SI)(CX*1), R11 + ADCQ $0x01, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + ADDQ 16(SI)(CX*1), R10 + ADCQ 24(SI)(CX*1), R11 + ADCQ $0x01, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 32(SI)(CX*1), R10 + ADCQ 40(SI)(CX*1), R11 + ADCQ $0x01, R12 + LEAQ 48(CX), CX + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 + VPSRLD $0x14, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 ADCQ DX, R15 + VPADDD Y14, Y0, Y0 + VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 + VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 + VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + VPXOR Y12, Y14, Y14 + VPXOR Y13, Y9, Y9 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 + VPSRLD $0x19, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + CMPQ CX, $0x000001e0 + JNE openAVX2InternalLoop + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + + // We only hashed 480 of the 512 bytes available - hash the remaining 32 here + ADDQ 480(SI), R10 + ADCQ 488(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + + // and here + ADDQ 496(SI), R10 + ADCQ 504(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + VPXOR 384(SI), Y0, Y0 + VPXOR 416(SI), Y14, Y14 + VPXOR 448(SI), Y12, Y12 + VPXOR 480(SI), Y4, Y4 + VMOVDQU Y0, 384(DI) + VMOVDQU Y14, 416(DI) + VMOVDQU Y12, 448(DI) + VMOVDQU Y4, 480(DI) + LEAQ 512(SI), SI + LEAQ 512(DI), DI + SUBQ $0x00000200, BX + JMP openAVX2MainLoop + +openAVX2MainLoopDone: + // Handle the various tail sizes efficiently + TESTQ BX, BX + JE openSSEFinalize + CMPQ BX, $0x80 + JBE openAVX2Tail128 + CMPQ BX, $0x00000100 + JBE openAVX2Tail256 + CMPQ BX, $0x00000180 + JBE openAVX2Tail384 + JMP openAVX2Tail512 + +openAVX2192: + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VMOVDQA Y4, Y2 + VMOVDQA Y1, Y15 + MOVQ $0x0000000a, R9 + +openAVX2192InnerCipherLoop: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + DECQ R9 + JNE openAVX2192InnerCipherLoop + VPADDD Y6, Y0, Y0 + VPADDD Y6, Y5, Y5 + VPADDD Y10, Y14, Y14 + VPADDD Y10, Y9, Y9 + VPADDD Y8, Y12, Y12 + VPADDD Y8, Y13, Y13 + VPADDD Y2, Y4, Y4 + VPADDD Y15, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y3 + + // Clamp and store poly key + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) + + // Stream for up to 192 bytes + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + +openAVX2ShortOpen: + // Hash + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + +openAVX2ShortOpenLoop: + CMPQ BX, $0x20 + JB openAVX2ShortTail32 + SUBQ $0x20, BX + + // Load for hashing + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ 16(SI), R10 + ADCQ 24(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + + // Load for decryption + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI + LEAQ 32(DI), DI + + // Shift stream left + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 + VMOVDQA Y5, Y4 + VMOVDQA Y9, Y5 + VMOVDQA Y13, Y9 + VMOVDQA Y1, Y13 + VMOVDQA Y6, Y1 + VMOVDQA Y10, Y6 + JMP openAVX2ShortOpenLoop + +openAVX2ShortTail32: + CMPQ BX, $0x10 + VMOVDQA X0, X1 + JB openAVX2ShortDone + SUBQ $0x10, BX + + // Load for hashing + ADDQ (SI), R10 + ADCQ 8(SI), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + + // Load for decryption + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 + +openAVX2ShortDone: + VZEROUPPER + JMP openSSETail16 + +openAVX2320: + VMOVDQA Y0, Y5 + VMOVDQA Y14, Y9 + VMOVDQA Y12, Y13 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y0, Y6 + VMOVDQA Y14, Y10 + VMOVDQA Y12, Y8 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y14, Y7 + VMOVDQA Y12, Y11 + VMOVDQA Y4, Y15 + MOVQ $0x0000000a, R9 + +openAVX2320InnerCipherLoop: + VPADDD Y14, Y0, Y0 VPXOR Y0, Y4, Y4 - VPXOR Y5, Y1, Y1 - VPXOR Y6, Y2, Y2 - VPXOR Y7, Y3, Y3 VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y1, Y1 - VPSHUFB ·rol16<>+0(SB), Y2, Y2 - VPSHUFB ·rol16<>+0(SB), Y3, Y3 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 VPADDD Y4, Y12, Y12 - VPADDD Y1, Y13, Y13 - VPADDD Y2, Y8, Y8 - VPADDD Y3, Y15, Y15 VPXOR Y12, Y14, Y14 - VPXOR Y13, Y9, Y9 - VPXOR Y8, Y10, Y10 - VPXOR Y15, Y11, Y11 - IMULQ R12, DX - ADDQ AX, R15 - ADCQ DX, R8 - VMOVDQA Y15, 224(BP) - VPSLLD $0x0c, Y14, Y15 + VPSLLD $0x0c, Y14, Y3 VPSRLD $0x14, Y14, Y14 - VPXOR Y15, Y14, Y14 - VPSLLD $0x0c, Y9, Y15 - VPSRLD $0x14, Y9, Y9 - VPXOR Y15, Y9, Y9 - VPSLLD $0x0c, Y10, Y15 - VPSRLD $0x14, Y10, Y10 - VPXOR Y15, Y10, Y10 - VPSLLD $0x0c, Y11, Y15 - VPSRLD $0x14, Y11, Y11 - VPXOR Y15, Y11, Y11 - VMOVDQA 224(BP), Y15 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 + VPXOR Y3, Y14, Y14 VPADDD Y14, Y0, Y0 - VPADDD Y9, Y5, Y5 - VPADDD Y10, Y6, Y6 - VPADDD Y11, Y7, Y7 VPXOR Y0, Y4, Y4 - VPXOR Y5, Y1, Y1 - VPXOR Y6, Y2, Y2 - VPXOR Y7, Y3, Y3 VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y1, Y1 - VPSHUFB ·rol8<>+0(SB), Y2, Y2 - VPSHUFB ·rol8<>+0(SB), Y3, Y3 - ADDQ 16(SI)(CX*1), R10 - ADCQ 24(SI)(CX*1), R11 - ADCQ $0x01, R12 VPADDD Y4, Y12, Y12 - VPADDD Y1, Y13, Y13 - VPADDD Y2, Y8, Y8 - VPADDD Y3, Y15, Y15 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 - IMULQ R12, R15 - MULXQ R11, AX, DX - ADDQ AX, R14 - ADCQ DX, R15 VPXOR Y12, Y14, Y14 - VPXOR Y13, Y9, Y9 - VPXOR Y8, Y10, Y10 - VPXOR Y15, Y11, Y11 - VMOVDQA Y15, 224(BP) - VPSLLD $0x07, Y14, Y15 + VPSLLD $0x07, Y14, Y3 VPSRLD $0x19, Y14, Y14 - VPXOR Y15, Y14, Y14 - VPSLLD $0x07, Y9, Y15 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 VPSRLD $0x19, Y9, Y9 - VPXOR Y15, Y9, Y9 - VPSLLD $0x07, Y10, Y15 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x07, Y10, Y3 VPSRLD $0x19, Y10, Y10 - VPXOR Y15, Y10, Y10 - VPSLLD $0x07, Y11, Y15 - VPSRLD $0x19, Y11, Y11 - VPXOR Y15, Y11, Y11 - VMOVDQA 224(BP), Y15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 + VPXOR Y3, Y10, Y10 VPALIGNR $0x04, Y14, Y14, Y14 VPALIGNR $0x04, Y9, Y9, Y9 VPALIGNR $0x04, Y10, Y10, Y10 - VPALIGNR $0x04, Y11, Y11, Y11 VPALIGNR $0x08, Y12, Y12, Y12 VPALIGNR $0x08, Y13, Y13, Y13 VPALIGNR $0x08, Y8, Y8, Y8 - VPALIGNR $0x08, Y15, Y15, Y15 VPALIGNR $0x0c, Y4, Y4, Y4 VPALIGNR $0x0c, Y1, Y1, Y1 VPALIGNR $0x0c, Y2, Y2, Y2 - VPALIGNR $0x0c, Y3, Y3, Y3 VPADDD Y14, Y0, Y0 - VPADDD Y9, Y5, Y5 - VPADDD Y10, Y6, Y6 - VPADDD Y11, Y7, Y7 - IMULQ R12, DX - ADDQ AX, R15 - ADCQ DX, R8 VPXOR Y0, Y4, Y4 - VPXOR Y5, Y1, Y1 - VPXOR Y6, Y2, Y2 - VPXOR Y7, Y3, Y3 VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y1, Y1 - VPSHUFB ·rol16<>+0(SB), Y2, Y2 - VPSHUFB ·rol16<>+0(SB), Y3, Y3 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 VPADDD Y4, Y12, Y12 - VPADDD Y1, Y13, Y13 - VPADDD Y2, Y8, Y8 - VPADDD Y3, Y15, Y15 VPXOR Y12, Y14, Y14 - VPXOR Y13, Y9, Y9 - VPXOR Y8, Y10, Y10 - VPXOR Y15, Y11, Y11 - ADDQ 32(SI)(CX*1), R10 - ADCQ 40(SI)(CX*1), R11 - ADCQ $0x01, R12 - LEAQ 48(CX), CX - VMOVDQA Y15, 224(BP) - VPSLLD $0x0c, Y14, Y15 + VPSLLD $0x0c, Y14, Y3 VPSRLD $0x14, Y14, Y14 - VPXOR Y15, Y14, Y14 - VPSLLD $0x0c, Y9, Y15 - VPSRLD $0x14, Y9, Y9 - VPXOR Y15, Y9, Y9 - VPSLLD $0x0c, Y10, Y15 - VPSRLD $0x14, Y10, Y10 - VPXOR Y15, Y10, Y10 - VPSLLD $0x0c, Y11, Y15 - VPSRLD $0x14, Y11, Y11 - VPXOR Y15, Y11, Y11 - VMOVDQA 224(BP), Y15 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 - IMULQ R12, R15 - MULXQ R11, AX, DX - ADDQ AX, R14 - ADCQ DX, R15 + VPXOR Y3, Y14, Y14 VPADDD Y14, Y0, Y0 - VPADDD Y9, Y5, Y5 - VPADDD Y10, Y6, Y6 - VPADDD Y11, Y7, Y7 VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y10, Y6, Y6 + VPXOR Y6, Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPADDD Y2, Y8, Y8 + VPXOR Y8, Y10, Y10 + VPSLLD $0x0c, Y10, Y3 + VPSRLD $0x14, Y10, Y10 + VPXOR Y3, Y10, Y10 + VPADDD Y10, Y6, Y6 VPXOR Y6, Y2, Y2 - VPXOR Y7, Y3, Y3 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y1, Y1 VPSHUFB ·rol8<>+0(SB), Y2, Y2 - VPSHUFB ·rol8<>+0(SB), Y3, Y3 - VPADDD Y4, Y12, Y12 - VPADDD Y1, Y13, Y13 VPADDD Y2, Y8, Y8 - VPADDD Y3, Y15, Y15 - IMULQ R12, DX - ADDQ AX, R15 - ADCQ DX, R8 - VPXOR Y12, Y14, Y14 - VPXOR Y13, Y9, Y9 VPXOR Y8, Y10, Y10 - VPXOR Y15, Y11, Y11 - VMOVDQA Y15, 224(BP) - VPSLLD $0x07, Y14, Y15 - VPSRLD $0x19, Y14, Y14 - VPXOR Y15, Y14, Y14 - VPSLLD $0x07, Y9, Y15 - VPSRLD $0x19, Y9, Y9 - VPXOR Y15, Y9, Y9 - VPSLLD $0x07, Y10, Y15 + VPSLLD $0x07, Y10, Y3 VPSRLD $0x19, Y10, Y10 - VPXOR Y15, Y10, Y10 - VPSLLD $0x07, Y11, Y15 - VPSRLD $0x19, Y11, Y11 - VPXOR Y15, Y11, Y11 - VMOVDQA 224(BP), Y15 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 + VPXOR Y3, Y10, Y10 VPALIGNR $0x0c, Y14, Y14, Y14 VPALIGNR $0x0c, Y9, Y9, Y9 VPALIGNR $0x0c, Y10, Y10, Y10 - VPALIGNR $0x0c, Y11, Y11, Y11 VPALIGNR $0x08, Y12, Y12, Y12 VPALIGNR $0x08, Y13, Y13, Y13 VPALIGNR $0x08, Y8, Y8, Y8 - VPALIGNR $0x08, Y15, Y15, Y15 VPALIGNR $0x04, Y4, Y4, Y4 VPALIGNR $0x04, Y1, Y1, Y1 VPALIGNR $0x04, Y2, Y2, Y2 - VPALIGNR $0x04, Y3, Y3, Y3 - CMPQ CX, $0x000001e0 - JNE openAVX2InternalLoop - VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 - VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 - VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 - VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 - VPADDD 32(BP), Y14, Y14 - VPADDD 32(BP), Y9, Y9 - VPADDD 32(BP), Y10, Y10 - VPADDD 32(BP), Y11, Y11 - VPADDD 64(BP), Y12, Y12 - VPADDD 64(BP), Y13, Y13 - VPADDD 64(BP), Y8, Y8 - VPADDD 64(BP), Y15, Y15 - VPADDD 96(BP), Y4, Y4 - VPADDD 128(BP), Y1, Y1 - VPADDD 160(BP), Y2, Y2 - VPADDD 192(BP), Y3, Y3 - VMOVDQA Y15, 224(BP) - - // We only hashed 480 of the 512 bytes available - hash the remaining 32 here - ADDQ 480(SI), R10 - ADCQ 488(SI), R11 - ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 - IMULQ R12, R15 - MULXQ R11, AX, DX - ADDQ AX, R14 - ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX - ADDQ AX, R15 - ADCQ DX, R8 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - VPERM2I128 $0x02, Y0, Y14, Y15 - VPERM2I128 $0x13, Y0, Y14, Y14 - VPERM2I128 $0x02, Y12, Y4, Y0 - VPERM2I128 $0x13, Y12, Y4, Y12 - VPXOR (SI), Y15, Y15 - VPXOR 32(SI), Y0, Y0 - VPXOR 64(SI), Y14, Y14 - VPXOR 96(SI), Y12, Y12 - VMOVDQU Y15, (DI) - VMOVDQU Y0, 32(DI) - VMOVDQU Y14, 64(DI) - VMOVDQU Y12, 96(DI) - VPERM2I128 $0x02, Y5, Y9, Y0 - VPERM2I128 $0x02, Y13, Y1, Y14 - VPERM2I128 $0x13, Y5, Y9, Y12 - VPERM2I128 $0x13, Y13, Y1, Y4 - VPXOR 128(SI), Y0, Y0 - VPXOR 160(SI), Y14, Y14 - VPXOR 192(SI), Y12, Y12 - VPXOR 224(SI), Y4, Y4 - VMOVDQU Y0, 128(DI) - VMOVDQU Y14, 160(DI) - VMOVDQU Y12, 192(DI) - VMOVDQU Y4, 224(DI) + DECQ R9 + JNE openAVX2320InnerCipherLoop + VMOVDQA ·chacha20Constants<>+0(SB), Y3 + VPADDD Y3, Y0, Y0 + VPADDD Y3, Y5, Y5 + VPADDD Y3, Y6, Y6 + VPADDD Y7, Y14, Y14 + VPADDD Y7, Y9, Y9 + VPADDD Y7, Y10, Y10 + VPADDD Y11, Y12, Y12 + VPADDD Y11, Y13, Y13 + VPADDD Y11, Y8, Y8 + VMOVDQA ·avx2IncMask<>+0(SB), Y3 + VPADDD Y15, Y4, Y4 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y1, Y1 + VPADDD Y3, Y15, Y15 + VPADDD Y15, Y2, Y2 - // and here - ADDQ 496(SI), R10 - ADCQ 504(SI), R11 - ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 - IMULQ R12, R15 - MULXQ R11, AX, DX - ADDQ AX, R14 - ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX - ADDQ AX, R15 - ADCQ DX, R8 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - VPERM2I128 $0x02, Y6, Y10, Y0 - VPERM2I128 $0x02, Y8, Y2, Y14 - VPERM2I128 $0x13, Y6, Y10, Y12 - VPERM2I128 $0x13, Y8, Y2, Y4 - VPXOR 256(SI), Y0, Y0 - VPXOR 288(SI), Y14, Y14 - VPXOR 320(SI), Y12, Y12 - VPXOR 352(SI), Y4, Y4 - VMOVDQU Y0, 256(DI) - VMOVDQU Y14, 288(DI) - VMOVDQU Y12, 320(DI) - VMOVDQU Y4, 352(DI) - VPERM2I128 $0x02, Y7, Y11, Y0 - VPERM2I128 $0x02, 224(BP), Y3, Y14 - VPERM2I128 $0x13, Y7, Y11, Y12 - VPERM2I128 $0x13, 224(BP), Y3, Y4 - VPXOR 384(SI), Y0, Y0 - VPXOR 416(SI), Y14, Y14 - VPXOR 448(SI), Y12, Y12 - VPXOR 480(SI), Y4, Y4 - VMOVDQU Y0, 384(DI) - VMOVDQU Y14, 416(DI) - VMOVDQU Y12, 448(DI) - VMOVDQU Y4, 480(DI) - LEAQ 512(SI), SI - LEAQ 512(DI), DI - SUBQ $0x00000200, BX - JMP openAVX2MainLoop + // Clamp and store poly key + VPERM2I128 $0x02, Y0, Y14, Y3 + VPAND ·polyClampMask<>+0(SB), Y3, Y3 + VMOVDQA Y3, (BP) -openAVX2MainLoopDone: - // Handle the various tail sizes efficiently - TESTQ BX, BX - JE openSSEFinalize - CMPQ BX, $0x80 - JBE openAVX2Tail128 - CMPQ BX, $0x00000100 - JBE openAVX2Tail256 - CMPQ BX, $0x00000180 - JBE openAVX2Tail384 - JMP openAVX2Tail512 + // Stream for up to 320 bytes + VPERM2I128 $0x13, Y0, Y14, Y0 + VPERM2I128 $0x13, Y12, Y4, Y14 + VPERM2I128 $0x02, Y5, Y9, Y12 + VPERM2I128 $0x02, Y13, Y1, Y4 + VPERM2I128 $0x13, Y5, Y9, Y5 + VPERM2I128 $0x13, Y13, Y1, Y9 + VPERM2I128 $0x02, Y6, Y10, Y13 + VPERM2I128 $0x02, Y8, Y2, Y1 + VPERM2I128 $0x13, Y6, Y10, Y6 + VPERM2I128 $0x13, Y8, Y2, Y10 + JMP openAVX2ShortOpen -openSSEFinalize: - // Hash in the PT, AAD lengths - ADDQ ad_len+80(FP), R10 - ADCQ src_len+56(FP), R11 +openAVX2Tail128: + // Need to decrypt up to 128 bytes - prepare two blocks + VMOVDQA ·chacha20Constants<>+0(SB), Y5 + VMOVDQA 32(BP), Y9 + VMOVDQA 64(BP), Y13 + VMOVDQA 192(BP), Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y1 + VMOVDQA Y1, Y4 + XORQ R9, R9 + MOVQ BX, CX + ANDQ $-16, CX + TESTQ CX, CX + JE openAVX2Tail128LoopB + +openAVX2Tail128LoopA: + ADDQ (SI)(R9*1), R10 + ADCQ 8(SI)(R9*1), R11 ADCQ $0x01, R12 - MOVQ (BP), AX - MOVQ AX, R15 - MULQ R10 - MOVQ AX, R13 - MOVQ DX, R14 - MOVQ (BP), AX - MULQ R11 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 IMULQ R12, R15 + MULXQ R11, AX, DX ADDQ AX, R14 ADCQ DX, R15 - MOVQ 8(BP), AX - MOVQ AX, R8 - MULQ R10 - ADDQ AX, R14 - ADCQ $0x00, DX - MOVQ DX, R10 - MOVQ 8(BP), AX - MULQ R11 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX ADDQ AX, R15 - ADCQ $0x00, DX - IMULQ R12, R8 - ADDQ R10, R15 ADCQ DX, R8 MOVQ R13, R10 MOVQ R14, R11 @@ -798,129 +3704,8 @@ openSSEFinalize: ADCQ R8, R11 ADCQ $0x00, R12 - // Final reduce - MOVQ R10, R13 - MOVQ R11, R14 - MOVQ R12, R15 - SUBQ $-5, R10 - SBBQ $-1, R11 - SBBQ $0x03, R12 - CMOVQCS R13, R10 - CMOVQCS R14, R11 - CMOVQCS R15, R12 - - // Add in the "s" part of the key - ADDQ 16(BP), R10 - ADCQ 24(BP), R11 - - // Finally, constant time compare to the tag at the end of the message - XORQ AX, AX - MOVQ $0x00000001, DX - XORQ (SI), R10 - XORQ 8(SI), R11 - ORQ R11, R10 - CMOVQEQ DX, AX - - // Return true iff tags are equal - MOVB AX, ret+96(FP) - RET - -openSSETail16: - TESTQ BX, BX - JE openSSEFinalize - - // We can safely load the CT from the end, because it is padded with the MAC - MOVQ BX, R9 - SHLQ $0x04, R9 - LEAQ ·andMask<>+0(SB), R13 - MOVOU (SI), X12 - ADDQ BX, SI - PAND -16(R13)(R9*1), X12 - MOVO X12, 64(BP) - MOVQ X12, R13 - MOVQ 72(BP), R14 - PXOR X1, X12 - - // We can only store one byte at a time, since plaintext can be shorter than 16 bytes -openSSETail16Store: - MOVQ X12, R8 - MOVB R8, (DI) - PSRLDQ $0x01, X12 - INCQ DI - DECQ BX - JNE openSSETail16Store - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x01, R12 - MOVQ (BP), AX - MOVQ AX, R15 - MULQ R10 - MOVQ AX, R13 - MOVQ DX, R14 - MOVQ (BP), AX - MULQ R11 - IMULQ R12, R15 - ADDQ AX, R14 - ADCQ DX, R15 - MOVQ 8(BP), AX - MOVQ AX, R8 - MULQ R10 - ADDQ AX, R14 - ADCQ $0x00, DX - MOVQ DX, R10 - MOVQ 8(BP), AX - MULQ R11 - ADDQ AX, R15 - ADCQ $0x00, DX - IMULQ R12, R8 - ADDQ R10, R15 - ADCQ DX, R8 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - JMP openSSEFinalize - -openAVX2192: - VMOVDQA Y0, Y5 - VMOVDQA Y14, Y9 - VMOVDQA Y12, Y13 - VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 - VMOVDQA Y0, Y6 - VMOVDQA Y14, Y10 - VMOVDQA Y12, Y8 - VMOVDQA Y4, Y2 - VMOVDQA Y1, Y15 - MOVQ $0x0000000a, R9 - -openAVX2192InnerCipherLoop: - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x0c, Y14, Y3 - VPSRLD $0x14, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x07, Y14, Y3 - VPSRLD $0x19, Y14, Y14 - VPXOR Y3, Y14, Y14 +openAVX2Tail128LoopB: + ADDQ $0x10, R9 VPADDD Y9, Y5, Y5 VPXOR Y5, Y1, Y1 VPSHUFB ·rol16<>+0(SB), Y1, Y1 @@ -937,28 +3722,9 @@ openAVX2192InnerCipherLoop: VPSLLD $0x07, Y9, Y3 VPSRLD $0x19, Y9, Y9 VPXOR Y3, Y9, Y9 - VPALIGNR $0x04, Y14, Y14, Y14 VPALIGNR $0x04, Y9, Y9, Y9 - VPALIGNR $0x08, Y12, Y12, Y12 VPALIGNR $0x08, Y13, Y13, Y13 - VPALIGNR $0x0c, Y4, Y4, Y4 VPALIGNR $0x0c, Y1, Y1, Y1 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x0c, Y14, Y3 - VPSRLD $0x14, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x07, Y14, Y3 - VPSRLD $0x19, Y14, Y14 - VPXOR Y3, Y14, Y14 VPADDD Y9, Y5, Y5 VPXOR Y5, Y1, Y1 VPSHUFB ·rol16<>+0(SB), Y1, Y1 @@ -975,49 +3741,82 @@ openAVX2192InnerCipherLoop: VPSLLD $0x07, Y9, Y3 VPSRLD $0x19, Y9, Y9 VPXOR Y3, Y9, Y9 - VPALIGNR $0x0c, Y14, Y14, Y14 VPALIGNR $0x0c, Y9, Y9, Y9 - VPALIGNR $0x08, Y12, Y12, Y12 VPALIGNR $0x08, Y13, Y13, Y13 - VPALIGNR $0x04, Y4, Y4, Y4 VPALIGNR $0x04, Y1, Y1, Y1 - DECQ R9 - JNE openAVX2192InnerCipherLoop - VPADDD Y6, Y0, Y0 - VPADDD Y6, Y5, Y5 - VPADDD Y10, Y14, Y14 - VPADDD Y10, Y9, Y9 - VPADDD Y8, Y12, Y12 - VPADDD Y8, Y13, Y13 - VPADDD Y2, Y4, Y4 - VPADDD Y15, Y1, Y1 - VPERM2I128 $0x02, Y0, Y14, Y3 + CMPQ R9, CX + JB openAVX2Tail128LoopA + CMPQ R9, $0xa0 + JNE openAVX2Tail128LoopB + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y13, Y13 + VPADDD Y4, Y1, Y1 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 - // Clamp and store poly key - VPAND ·polyClampMask<>+0(SB), Y3, Y3 - VMOVDQA Y3, (BP) +openAVX2TailLoop: + CMPQ BX, $0x20 + JB openAVX2Tail + SUBQ $0x20, BX - // Stream for up to 192 bytes - VPERM2I128 $0x13, Y0, Y14, Y0 - VPERM2I128 $0x13, Y12, Y4, Y14 - VPERM2I128 $0x02, Y5, Y9, Y12 - VPERM2I128 $0x02, Y13, Y1, Y4 - VPERM2I128 $0x13, Y5, Y9, Y5 - VPERM2I128 $0x13, Y13, Y1, Y9 + // Load for decryption + VPXOR (SI), Y0, Y0 + VMOVDQU Y0, (DI) + LEAQ 32(SI), SI + LEAQ 32(DI), DI + VMOVDQA Y14, Y0 + VMOVDQA Y12, Y14 + VMOVDQA Y4, Y12 + JMP openAVX2TailLoop -openAVX2ShortOpen: - // Hash - MOVQ ad_len+80(FP), R9 - CALL polyHashADInternal<>(SB) +openAVX2Tail: + CMPQ BX, $0x10 + VMOVDQA X0, X1 + JB openAVX2TailDone + SUBQ $0x10, BX + + // Load for decryption + VPXOR (SI), X0, X12 + VMOVDQU X12, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI + VPERM2I128 $0x11, Y0, Y0, Y0 + VMOVDQA X0, X1 + +openAVX2TailDone: + VZEROUPPER + JMP openSSETail16 + +openAVX2Tail256: + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VMOVDQA Y4, Y7 + VMOVDQA Y1, Y11 -openAVX2ShortOpenLoop: - CMPQ BX, $0x20 - JB openAVX2ShortTail32 - SUBQ $0x20, BX + // Compute the number of iterations that will hash data + MOVQ BX, 224(BP) + MOVQ BX, CX + SUBQ $0x80, CX + SHRQ $0x04, CX + MOVQ $0x0000000a, R9 + CMPQ CX, $0x0a + CMOVQGT R9, CX + MOVQ SI, BX + XORQ R9, R9 - // Load for hashing - ADDQ (SI), R10 - ADCQ 8(SI), R11 +openAVX2Tail256LoopA: + ADDQ (BX), R10 + ADCQ 8(BX), R11 ADCQ $0x01, R12 MOVQ (BP), DX MOVQ DX, R15 @@ -1050,8 +3849,101 @@ openAVX2ShortOpenLoop: ADDQ R15, R10 ADCQ R8, R11 ADCQ $0x00, R12 - ADDQ 16(SI), R10 - ADCQ 24(SI), R11 + LEAQ 16(BX), BX + +openAVX2Tail256LoopB: + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x04, Y14, Y14, Y14 + VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x0c, Y4, Y4, Y4 + VPALIGNR $0x0c, Y1, Y1, Y1 + INCQ R9 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x0c, Y14, Y3 + VPSRLD $0x14, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y14, Y0, Y0 + VPXOR Y0, Y4, Y4 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 + VPADDD Y4, Y12, Y12 + VPXOR Y12, Y14, Y14 + VPSLLD $0x07, Y14, Y3 + VPSRLD $0x19, Y14, Y14 + VPXOR Y3, Y14, Y14 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x0c, Y9, Y3 + VPSRLD $0x14, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPADDD Y9, Y5, Y5 + VPXOR Y5, Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPADDD Y1, Y13, Y13 + VPXOR Y13, Y9, Y9 + VPSLLD $0x07, Y9, Y3 + VPSRLD $0x19, Y9, Y9 + VPXOR Y3, Y9, Y9 + VPALIGNR $0x0c, Y14, Y14, Y14 + VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x08, Y12, Y12, Y12 + VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x04, Y4, Y4, Y4 + VPALIGNR $0x04, Y1, Y1, Y1 + CMPQ R9, CX + JB openAVX2Tail256LoopA + CMPQ R9, $0x0a + JNE openAVX2Tail256LoopB + MOVQ BX, R9 + SUBQ SI, BX + MOVQ BX, CX + MOVQ 224(BP), BX + +openAVX2Tail256Hash: + ADDQ $0x10, CX + CMPQ CX, BX + JGT openAVX2Tail256HashEnd + ADDQ (R9), R10 + ADCQ 8(R9), R11 ADCQ $0x01, R12 MOVQ (BP), DX MOVQ DX, R15 @@ -1084,34 +3976,73 @@ openAVX2ShortOpenLoop: ADDQ R15, R10 ADCQ R8, R11 ADCQ $0x00, R12 + LEAQ 16(R9), R9 + JMP openAVX2Tail256Hash - // Load for decryption - VPXOR (SI), Y0, Y0 - VMOVDQU Y0, (DI) - LEAQ 32(SI), SI - LEAQ 32(DI), DI +openAVX2Tail256HashEnd: + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 + VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD 32(BP), Y14, Y14 + VPADDD 32(BP), Y9, Y9 + VPADDD 64(BP), Y12, Y12 + VPADDD 64(BP), Y13, Y13 + VPADDD Y7, Y4, Y4 + VPADDD Y11, Y1, Y1 + VPERM2I128 $0x02, Y0, Y14, Y6 + VPERM2I128 $0x02, Y12, Y4, Y10 + VPERM2I128 $0x13, Y0, Y14, Y8 + VPERM2I128 $0x13, Y12, Y4, Y2 + VPERM2I128 $0x02, Y5, Y9, Y0 + VPERM2I128 $0x02, Y13, Y1, Y14 + VPERM2I128 $0x13, Y5, Y9, Y12 + VPERM2I128 $0x13, Y13, Y1, Y4 + VPXOR (SI), Y6, Y6 + VPXOR 32(SI), Y10, Y10 + VPXOR 64(SI), Y8, Y8 + VPXOR 96(SI), Y2, Y2 + VMOVDQU Y6, (DI) + VMOVDQU Y10, 32(DI) + VMOVDQU Y8, 64(DI) + VMOVDQU Y2, 96(DI) + LEAQ 128(SI), SI + LEAQ 128(DI), DI + SUBQ $0x80, BX + JMP openAVX2TailLoop - // Shift stream left - VMOVDQA Y14, Y0 - VMOVDQA Y12, Y14 - VMOVDQA Y4, Y12 - VMOVDQA Y5, Y4 - VMOVDQA Y9, Y5 - VMOVDQA Y13, Y9 - VMOVDQA Y1, Y13 - VMOVDQA Y6, Y1 - VMOVDQA Y10, Y6 - JMP openAVX2ShortOpenLoop +openAVX2Tail384: + // Need to decrypt up to 384 bytes - prepare six blocks + VMOVDQA ·chacha20Constants<>+0(SB), Y0 + VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA 32(BP), Y14 + VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA 64(BP), Y12 + VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA 192(BP), Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 + VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) -openAVX2ShortTail32: - CMPQ BX, $0x10 - VMOVDQA X0, X1 - JB openAVX2ShortDone - SUBQ $0x10, BX + // Compute the number of iterations that will hash two blocks of data + MOVQ BX, 224(BP) + MOVQ BX, CX + SUBQ $0x00000100, CX + SHRQ $0x04, CX + ADDQ $0x06, CX + MOVQ $0x0000000a, R9 + CMPQ CX, $0x0a + CMOVQGT R9, CX + MOVQ SI, BX + XORQ R9, R9 - // Load for hashing - ADDQ (SI), R10 - ADCQ 8(SI), R11 +openAVX2Tail384LoopB: + ADDQ (BX), R10 + ADCQ 8(BX), R11 ADCQ $0x01, R12 MOVQ (BP), DX MOVQ DX, R15 @@ -1122,56 +4053,31 @@ openAVX2ShortTail32: ADCQ DX, R15 MOVQ 8(BP), DX MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX - ADDQ AX, R15 - ADCQ DX, R8 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - - // Load for decryption - VPXOR (SI), X0, X12 - VMOVDQU X12, (DI) - LEAQ 16(SI), SI - LEAQ 16(DI), DI - VPERM2I128 $0x11, Y0, Y0, Y0 - VMOVDQA X0, X1 - -openAVX2ShortDone: - VZEROUPPER - JMP openSSETail16 - -openAVX2320: - VMOVDQA Y0, Y5 - VMOVDQA Y14, Y9 - VMOVDQA Y12, Y13 - VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 - VMOVDQA Y0, Y6 - VMOVDQA Y14, Y10 - VMOVDQA Y12, Y8 - VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 - VMOVDQA Y14, Y7 - VMOVDQA Y12, Y11 - VMOVDQA Y4, Y15 - MOVQ $0x0000000a, R9 + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX -openAVX2320InnerCipherLoop: +openAVX2Tail384LoopA: VPADDD Y14, Y0, Y0 VPXOR Y0, Y4, Y4 VPSHUFB ·rol16<>+0(SB), Y4, Y4 @@ -1229,6 +4135,42 @@ openAVX2320InnerCipherLoop: VPALIGNR $0x0c, Y4, Y4, Y4 VPALIGNR $0x0c, Y1, Y1, Y1 VPALIGNR $0x0c, Y2, Y2, Y2 + ADDQ (BX), R10 + ADCQ 8(BX), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(BX), BX + INCQ R9 VPADDD Y14, Y0, Y0 VPXOR Y0, Y4, Y4 VPSHUFB ·rol16<>+0(SB), Y4, Y4 @@ -1286,60 +4228,21 @@ openAVX2320InnerCipherLoop: VPALIGNR $0x04, Y4, Y4, Y4 VPALIGNR $0x04, Y1, Y1, Y1 VPALIGNR $0x04, Y2, Y2, Y2 - DECQ R9 - JNE openAVX2320InnerCipherLoop - VMOVDQA ·chacha20Constants<>+0(SB), Y3 - VPADDD Y3, Y0, Y0 - VPADDD Y3, Y5, Y5 - VPADDD Y3, Y6, Y6 - VPADDD Y7, Y14, Y14 - VPADDD Y7, Y9, Y9 - VPADDD Y7, Y10, Y10 - VPADDD Y11, Y12, Y12 - VPADDD Y11, Y13, Y13 - VPADDD Y11, Y8, Y8 - VMOVDQA ·avx2IncMask<>+0(SB), Y3 - VPADDD Y15, Y4, Y4 - VPADDD Y3, Y15, Y15 - VPADDD Y15, Y1, Y1 - VPADDD Y3, Y15, Y15 - VPADDD Y15, Y2, Y2 - - // Clamp and store poly key - VPERM2I128 $0x02, Y0, Y14, Y3 - VPAND ·polyClampMask<>+0(SB), Y3, Y3 - VMOVDQA Y3, (BP) - - // Stream for up to 320 bytes - VPERM2I128 $0x13, Y0, Y14, Y0 - VPERM2I128 $0x13, Y12, Y4, Y14 - VPERM2I128 $0x02, Y5, Y9, Y12 - VPERM2I128 $0x02, Y13, Y1, Y4 - VPERM2I128 $0x13, Y5, Y9, Y5 - VPERM2I128 $0x13, Y13, Y1, Y9 - VPERM2I128 $0x02, Y6, Y10, Y13 - VPERM2I128 $0x02, Y8, Y2, Y1 - VPERM2I128 $0x13, Y6, Y10, Y6 - VPERM2I128 $0x13, Y8, Y2, Y10 - JMP openAVX2ShortOpen - -openAVX2Tail128: - // Need to decrypt up to 128 bytes - prepare two blocks - VMOVDQA ·chacha20Constants<>+0(SB), Y5 - VMOVDQA 32(BP), Y9 - VMOVDQA 64(BP), Y13 - VMOVDQA 192(BP), Y1 - VPADDD ·avx2IncMask<>+0(SB), Y1, Y1 - VMOVDQA Y1, Y4 - XORQ R9, R9 - MOVQ BX, CX - ANDQ $-16, CX - TESTQ CX, CX - JE openAVX2Tail128LoopB + CMPQ R9, CX + JB openAVX2Tail384LoopB + CMPQ R9, $0x0a + JNE openAVX2Tail384LoopA + MOVQ BX, R9 + SUBQ SI, BX + MOVQ BX, CX + MOVQ 224(BP), BX -openAVX2Tail128LoopA: - ADDQ (SI)(R9*1), R10 - ADCQ 8(SI)(R9*1), R11 +openAVX2Tail384Hash: + ADDQ $0x10, CX + CMPQ CX, BX + JGT openAVX2Tail384HashEnd + ADDQ (R9), R10 + ADCQ 8(R9), R11 ADCQ $0x01, R12 MOVQ (BP), DX MOVQ DX, R15 @@ -1372,120 +4275,83 @@ openAVX2Tail128LoopA: ADDQ R15, R10 ADCQ R8, R11 ADCQ $0x00, R12 + LEAQ 16(R9), R9 + JMP openAVX2Tail384Hash -openAVX2Tail128LoopB: - ADDQ $0x10, R9 - VPADDD Y9, Y5, Y5 - VPXOR Y5, Y1, Y1 - VPSHUFB ·rol16<>+0(SB), Y1, Y1 - VPADDD Y1, Y13, Y13 - VPXOR Y13, Y9, Y9 - VPSLLD $0x0c, Y9, Y3 - VPSRLD $0x14, Y9, Y9 - VPXOR Y3, Y9, Y9 - VPADDD Y9, Y5, Y5 - VPXOR Y5, Y1, Y1 - VPSHUFB ·rol8<>+0(SB), Y1, Y1 - VPADDD Y1, Y13, Y13 - VPXOR Y13, Y9, Y9 - VPSLLD $0x07, Y9, Y3 - VPSRLD $0x19, Y9, Y9 - VPXOR Y3, Y9, Y9 - VPALIGNR $0x04, Y9, Y9, Y9 - VPALIGNR $0x08, Y13, Y13, Y13 - VPALIGNR $0x0c, Y1, Y1, Y1 - VPADDD Y9, Y5, Y5 - VPXOR Y5, Y1, Y1 - VPSHUFB ·rol16<>+0(SB), Y1, Y1 - VPADDD Y1, Y13, Y13 - VPXOR Y13, Y9, Y9 - VPSLLD $0x0c, Y9, Y3 - VPSRLD $0x14, Y9, Y9 - VPXOR Y3, Y9, Y9 - VPADDD Y9, Y5, Y5 - VPXOR Y5, Y1, Y1 - VPSHUFB ·rol8<>+0(SB), Y1, Y1 - VPADDD Y1, Y13, Y13 - VPXOR Y13, Y9, Y9 - VPSLLD $0x07, Y9, Y3 - VPSRLD $0x19, Y9, Y9 - VPXOR Y3, Y9, Y9 - VPALIGNR $0x0c, Y9, Y9, Y9 - VPALIGNR $0x08, Y13, Y13, Y13 - VPALIGNR $0x04, Y1, Y1, Y1 - CMPQ R9, CX - JB openAVX2Tail128LoopA - CMPQ R9, $0xa0 - JNE openAVX2Tail128LoopB +openAVX2Tail384HashEnd: + VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD 32(BP), Y14, Y14 VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 64(BP), Y12, Y12 VPADDD 64(BP), Y13, Y13 - VPADDD Y4, Y1, Y1 - VPERM2I128 $0x02, Y5, Y9, Y0 - VPERM2I128 $0x02, Y13, Y1, Y14 - VPERM2I128 $0x13, Y5, Y9, Y12 - VPERM2I128 $0x13, Y13, Y1, Y4 - -openAVX2TailLoop: - CMPQ BX, $0x20 - JB openAVX2Tail - SUBQ $0x20, BX - - // Load for decryption - VPXOR (SI), Y0, Y0 - VMOVDQU Y0, (DI) - LEAQ 32(SI), SI - LEAQ 32(DI), DI - VMOVDQA Y14, Y0 - VMOVDQA Y12, Y14 - VMOVDQA Y4, Y12 - JMP openAVX2TailLoop - -openAVX2Tail: - CMPQ BX, $0x10 - VMOVDQA X0, X1 - JB openAVX2TailDone - SUBQ $0x10, BX - - // Load for decryption - VPXOR (SI), X0, X12 - VMOVDQU X12, (DI) - LEAQ 16(SI), SI - LEAQ 16(DI), DI - VPERM2I128 $0x11, Y0, Y0, Y0 - VMOVDQA X0, X1 - -openAVX2TailDone: - VZEROUPPER - JMP openSSETail16 + VPADDD 64(BP), Y8, Y8 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPERM2I128 $0x02, Y0, Y14, Y3 + VPERM2I128 $0x02, Y12, Y4, Y7 + VPERM2I128 $0x13, Y0, Y14, Y11 + VPERM2I128 $0x13, Y12, Y4, Y15 + VPXOR (SI), Y3, Y3 + VPXOR 32(SI), Y7, Y7 + VPXOR 64(SI), Y11, Y11 + VPXOR 96(SI), Y15, Y15 + VMOVDQU Y3, (DI) + VMOVDQU Y7, 32(DI) + VMOVDQU Y11, 64(DI) + VMOVDQU Y15, 96(DI) + VPERM2I128 $0x02, Y5, Y9, Y3 + VPERM2I128 $0x02, Y13, Y1, Y7 + VPERM2I128 $0x13, Y5, Y9, Y11 + VPERM2I128 $0x13, Y13, Y1, Y15 + VPXOR 128(SI), Y3, Y3 + VPXOR 160(SI), Y7, Y7 + VPXOR 192(SI), Y11, Y11 + VPXOR 224(SI), Y15, Y15 + VMOVDQU Y3, 128(DI) + VMOVDQU Y7, 160(DI) + VMOVDQU Y11, 192(DI) + VMOVDQU Y15, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + LEAQ 256(SI), SI + LEAQ 256(DI), DI + SUBQ $0x00000100, BX + JMP openAVX2TailLoop -openAVX2Tail256: - VMOVDQA ·chacha20Constants<>+0(SB), Y0 +openAVX2Tail512: + VMOVDQU ·chacha20Constants<>+0(SB), Y0 VMOVDQA Y0, Y5 + VMOVDQA Y0, Y6 + VMOVDQA Y0, Y7 VMOVDQA 32(BP), Y14 VMOVDQA Y14, Y9 + VMOVDQA Y14, Y10 + VMOVDQA Y14, Y11 VMOVDQA 64(BP), Y12 VMOVDQA Y12, Y13 + VMOVDQA Y12, Y8 + VMOVDQA Y12, Y15 VMOVDQA 192(BP), Y4 VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 - VMOVDQA Y4, Y7 - VMOVDQA Y1, Y11 - - // Compute the number of iterations that will hash data - MOVQ BX, 224(BP) - MOVQ BX, CX - SUBQ $0x80, CX - SHRQ $0x04, CX - MOVQ $0x0000000a, R9 - CMPQ CX, $0x0a - CMOVQGT R9, CX - MOVQ SI, BX - XORQ R9, R9 + VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 + VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 + VMOVDQA Y4, 96(BP) + VMOVDQA Y1, 128(BP) + VMOVDQA Y2, 160(BP) + VMOVDQA Y3, 192(BP) + XORQ CX, CX + MOVQ SI, R9 -openAVX2Tail256LoopA: - ADDQ (BX), R10 - ADCQ 8(BX), R11 +openAVX2Tail512LoopB: + ADDQ (R9), R10 + ADCQ 8(R9), R11 ADCQ $0x01, R12 MOVQ (BP), DX MOVQ DX, R15 @@ -1518,99 +4384,250 @@ openAVX2Tail256LoopA: ADDQ R15, R10 ADCQ R8, R11 ADCQ $0x00, R12 - LEAQ 16(BX), BX + LEAQ 16(R9), R9 -openAVX2Tail256LoopB: - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x0c, Y14, Y3 - VPSRLD $0x14, Y14, Y14 - VPXOR Y3, Y14, Y14 +openAVX2Tail512LoopA: VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x07, Y14, Y3 - VPSRLD $0x19, Y14, Y14 - VPXOR Y3, Y14, Y14 VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 VPXOR Y13, Y9, Y9 - VPSLLD $0x0c, Y9, Y3 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 VPSRLD $0x14, Y9, Y9 - VPXOR Y3, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + ADDQ (R9), R10 + ADCQ 8(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + VPADDD Y14, Y0, Y0 VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 VPXOR Y13, Y9, Y9 - VPSLLD $0x07, Y9, Y3 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 VPSRLD $0x19, Y9, Y9 - VPXOR Y3, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 VPALIGNR $0x04, Y14, Y14, Y14 VPALIGNR $0x04, Y9, Y9, Y9 + VPALIGNR $0x04, Y10, Y10, Y10 + VPALIGNR $0x04, Y11, Y11, Y11 VPALIGNR $0x08, Y12, Y12, Y12 VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 VPALIGNR $0x0c, Y4, Y4, Y4 VPALIGNR $0x0c, Y1, Y1, Y1 - INCQ R9 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x0c, Y14, Y3 - VPSRLD $0x14, Y14, Y14 - VPXOR Y3, Y14, Y14 + VPALIGNR $0x0c, Y2, Y2, Y2 + VPALIGNR $0x0c, Y3, Y3, Y3 VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x07, Y14, Y3 - VPSRLD $0x19, Y14, Y14 - VPXOR Y3, Y14, Y14 VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol16<>+0(SB), Y4, Y4 VPSHUFB ·rol16<>+0(SB), Y1, Y1 + VPSHUFB ·rol16<>+0(SB), Y2, Y2 + VPSHUFB ·rol16<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 VPXOR Y13, Y9, Y9 - VPSLLD $0x0c, Y9, Y3 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + ADDQ 16(R9), R10 + ADCQ 24(R9), R11 + ADCQ $0x01, R12 + MOVQ (BP), DX + MOVQ DX, R15 + MULXQ R10, R13, R14 + IMULQ R12, R15 + MULXQ R11, AX, DX + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), DX + MULXQ R10, R10, AX + ADDQ R10, R14 + MULXQ R11, R11, R8 + ADCQ R11, R15 + ADCQ $0x00, R8 + IMULQ R12, DX + ADDQ AX, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 32(R9), R9 + VMOVDQA Y15, 224(BP) + VPSLLD $0x0c, Y14, Y15 + VPSRLD $0x14, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x0c, Y9, Y15 VPSRLD $0x14, Y9, Y9 - VPXOR Y3, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x0c, Y10, Y15 + VPSRLD $0x14, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x0c, Y11, Y15 + VPSRLD $0x14, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 + VPADDD Y14, Y0, Y0 VPADDD Y9, Y5, Y5 + VPADDD Y10, Y6, Y6 + VPADDD Y11, Y7, Y7 + VPXOR Y0, Y4, Y4 VPXOR Y5, Y1, Y1 + VPXOR Y6, Y2, Y2 + VPXOR Y7, Y3, Y3 + VPSHUFB ·rol8<>+0(SB), Y4, Y4 VPSHUFB ·rol8<>+0(SB), Y1, Y1 + VPSHUFB ·rol8<>+0(SB), Y2, Y2 + VPSHUFB ·rol8<>+0(SB), Y3, Y3 + VPADDD Y4, Y12, Y12 VPADDD Y1, Y13, Y13 + VPADDD Y2, Y8, Y8 + VPADDD Y3, Y15, Y15 + VPXOR Y12, Y14, Y14 VPXOR Y13, Y9, Y9 - VPSLLD $0x07, Y9, Y3 + VPXOR Y8, Y10, Y10 + VPXOR Y15, Y11, Y11 + VMOVDQA Y15, 224(BP) + VPSLLD $0x07, Y14, Y15 + VPSRLD $0x19, Y14, Y14 + VPXOR Y15, Y14, Y14 + VPSLLD $0x07, Y9, Y15 VPSRLD $0x19, Y9, Y9 - VPXOR Y3, Y9, Y9 + VPXOR Y15, Y9, Y9 + VPSLLD $0x07, Y10, Y15 + VPSRLD $0x19, Y10, Y10 + VPXOR Y15, Y10, Y10 + VPSLLD $0x07, Y11, Y15 + VPSRLD $0x19, Y11, Y11 + VPXOR Y15, Y11, Y11 + VMOVDQA 224(BP), Y15 VPALIGNR $0x0c, Y14, Y14, Y14 VPALIGNR $0x0c, Y9, Y9, Y9 + VPALIGNR $0x0c, Y10, Y10, Y10 + VPALIGNR $0x0c, Y11, Y11, Y11 VPALIGNR $0x08, Y12, Y12, Y12 VPALIGNR $0x08, Y13, Y13, Y13 + VPALIGNR $0x08, Y8, Y8, Y8 + VPALIGNR $0x08, Y15, Y15, Y15 VPALIGNR $0x04, Y4, Y4, Y4 VPALIGNR $0x04, Y1, Y1, Y1 - CMPQ R9, CX - JB openAVX2Tail256LoopA - CMPQ R9, $0x0a - JNE openAVX2Tail256LoopB - MOVQ BX, R9 - SUBQ SI, BX + VPALIGNR $0x04, Y2, Y2, Y2 + VPALIGNR $0x04, Y3, Y3, Y3 + INCQ CX + CMPQ CX, $0x04 + JLT openAVX2Tail512LoopB + CMPQ CX, $0x0a + JNE openAVX2Tail512LoopA MOVQ BX, CX - MOVQ 224(BP), BX + SUBQ $0x00000180, CX + ANDQ $-16, CX -openAVX2Tail256Hash: - ADDQ $0x10, CX - CMPQ CX, BX - JGT openAVX2Tail256HashEnd +openAVX2Tail512HashLoop: + TESTQ CX, CX + JE openAVX2Tail512HashEnd ADDQ (R9), R10 ADCQ 8(R9), R11 ADCQ $0x01, R12 @@ -1646,88 +4663,1004 @@ openAVX2Tail256Hash: ADCQ R8, R11 ADCQ $0x00, R12 LEAQ 16(R9), R9 - JMP openAVX2Tail256Hash + SUBQ $0x10, CX + JMP openAVX2Tail512HashLoop -openAVX2Tail256HashEnd: +openAVX2Tail512HashEnd: VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 + VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 + VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 VPADDD 32(BP), Y14, Y14 VPADDD 32(BP), Y9, Y9 + VPADDD 32(BP), Y10, Y10 + VPADDD 32(BP), Y11, Y11 VPADDD 64(BP), Y12, Y12 VPADDD 64(BP), Y13, Y13 - VPADDD Y7, Y4, Y4 - VPADDD Y11, Y1, Y1 - VPERM2I128 $0x02, Y0, Y14, Y6 - VPERM2I128 $0x02, Y12, Y4, Y10 - VPERM2I128 $0x13, Y0, Y14, Y8 - VPERM2I128 $0x13, Y12, Y4, Y2 + VPADDD 64(BP), Y8, Y8 + VPADDD 64(BP), Y15, Y15 + VPADDD 96(BP), Y4, Y4 + VPADDD 128(BP), Y1, Y1 + VPADDD 160(BP), Y2, Y2 + VPADDD 192(BP), Y3, Y3 + VMOVDQA Y15, 224(BP) + VPERM2I128 $0x02, Y0, Y14, Y15 + VPERM2I128 $0x13, Y0, Y14, Y14 + VPERM2I128 $0x02, Y12, Y4, Y0 + VPERM2I128 $0x13, Y12, Y4, Y12 + VPXOR (SI), Y15, Y15 + VPXOR 32(SI), Y0, Y0 + VPXOR 64(SI), Y14, Y14 + VPXOR 96(SI), Y12, Y12 + VMOVDQU Y15, (DI) + VMOVDQU Y0, 32(DI) + VMOVDQU Y14, 64(DI) + VMOVDQU Y12, 96(DI) VPERM2I128 $0x02, Y5, Y9, Y0 VPERM2I128 $0x02, Y13, Y1, Y14 VPERM2I128 $0x13, Y5, Y9, Y12 VPERM2I128 $0x13, Y13, Y1, Y4 - VPXOR (SI), Y6, Y6 - VPXOR 32(SI), Y10, Y10 - VPXOR 64(SI), Y8, Y8 - VPXOR 96(SI), Y2, Y2 - VMOVDQU Y6, (DI) - VMOVDQU Y10, 32(DI) - VMOVDQU Y8, 64(DI) - VMOVDQU Y2, 96(DI) - LEAQ 128(SI), SI - LEAQ 128(DI), DI - SUBQ $0x80, BX + VPXOR 128(SI), Y0, Y0 + VPXOR 160(SI), Y14, Y14 + VPXOR 192(SI), Y12, Y12 + VPXOR 224(SI), Y4, Y4 + VMOVDQU Y0, 128(DI) + VMOVDQU Y14, 160(DI) + VMOVDQU Y12, 192(DI) + VMOVDQU Y4, 224(DI) + VPERM2I128 $0x02, Y6, Y10, Y0 + VPERM2I128 $0x02, Y8, Y2, Y14 + VPERM2I128 $0x13, Y6, Y10, Y12 + VPERM2I128 $0x13, Y8, Y2, Y4 + VPXOR 256(SI), Y0, Y0 + VPXOR 288(SI), Y14, Y14 + VPXOR 320(SI), Y12, Y12 + VPXOR 352(SI), Y4, Y4 + VMOVDQU Y0, 256(DI) + VMOVDQU Y14, 288(DI) + VMOVDQU Y12, 320(DI) + VMOVDQU Y4, 352(DI) + VPERM2I128 $0x02, Y7, Y11, Y0 + VPERM2I128 $0x02, 224(BP), Y3, Y14 + VPERM2I128 $0x13, Y7, Y11, Y12 + VPERM2I128 $0x13, 224(BP), Y3, Y4 + LEAQ 384(SI), SI + LEAQ 384(DI), DI + SUBQ $0x00000180, BX JMP openAVX2TailLoop -openAVX2Tail384: - // Need to decrypt up to 384 bytes - prepare six blocks - VMOVDQA ·chacha20Constants<>+0(SB), Y0 - VMOVDQA Y0, Y5 - VMOVDQA Y0, Y6 - VMOVDQA 32(BP), Y14 - VMOVDQA Y14, Y9 - VMOVDQA Y14, Y10 - VMOVDQA 64(BP), Y12 - VMOVDQA Y12, Y13 - VMOVDQA Y12, Y8 - VMOVDQA 192(BP), Y4 - VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 - VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 - VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 - VMOVDQA Y4, 96(BP) - VMOVDQA Y1, 128(BP) - VMOVDQA Y2, 160(BP) +DATA ·chacha20Constants<>+0(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+4(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+8(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+12(SB)/4, $0x6b206574 +DATA ·chacha20Constants<>+16(SB)/4, $0x61707865 +DATA ·chacha20Constants<>+20(SB)/4, $0x3320646e +DATA ·chacha20Constants<>+24(SB)/4, $0x79622d32 +DATA ·chacha20Constants<>+28(SB)/4, $0x6b206574 +GLOBL ·chacha20Constants<>(SB), RODATA|NOPTR, $32 - // Compute the number of iterations that will hash two blocks of data - MOVQ BX, 224(BP) - MOVQ BX, CX - SUBQ $0x00000100, CX - SHRQ $0x04, CX - ADDQ $0x06, CX - MOVQ $0x0000000a, R9 - CMPQ CX, $0x0a - CMOVQGT R9, CX - MOVQ SI, BX - XORQ R9, R9 +DATA ·polyClampMask<>+0(SB)/8, $0x0ffffffc0fffffff +DATA ·polyClampMask<>+8(SB)/8, $0x0ffffffc0ffffffc +DATA ·polyClampMask<>+16(SB)/8, $0xffffffffffffffff +DATA ·polyClampMask<>+24(SB)/8, $0xffffffffffffffff +GLOBL ·polyClampMask<>(SB), RODATA|NOPTR, $32 -openAVX2Tail384LoopB: - ADDQ (BX), R10 - ADCQ 8(BX), R11 +DATA ·sseIncMask<>+0(SB)/8, $0x0000000000000001 +DATA ·sseIncMask<>+8(SB)/8, $0x0000000000000000 +GLOBL ·sseIncMask<>(SB), RODATA|NOPTR, $16 + +DATA ·andMask<>+0(SB)/8, $0x00000000000000ff +DATA ·andMask<>+8(SB)/8, $0x0000000000000000 +DATA ·andMask<>+16(SB)/8, $0x000000000000ffff +DATA ·andMask<>+24(SB)/8, $0x0000000000000000 +DATA ·andMask<>+32(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+40(SB)/8, $0x0000000000000000 +DATA ·andMask<>+48(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+56(SB)/8, $0x0000000000000000 +DATA ·andMask<>+64(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+72(SB)/8, $0x0000000000000000 +DATA ·andMask<>+80(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+88(SB)/8, $0x0000000000000000 +DATA ·andMask<>+96(SB)/8, $0x00ffffffffffffff +DATA ·andMask<>+104(SB)/8, $0x0000000000000000 +DATA ·andMask<>+112(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+120(SB)/8, $0x0000000000000000 +DATA ·andMask<>+128(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+136(SB)/8, $0x00000000000000ff +DATA ·andMask<>+144(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+152(SB)/8, $0x000000000000ffff +DATA ·andMask<>+160(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+168(SB)/8, $0x0000000000ffffff +DATA ·andMask<>+176(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+184(SB)/8, $0x00000000ffffffff +DATA ·andMask<>+192(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+200(SB)/8, $0x000000ffffffffff +DATA ·andMask<>+208(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+216(SB)/8, $0x0000ffffffffffff +DATA ·andMask<>+224(SB)/8, $0xffffffffffffffff +DATA ·andMask<>+232(SB)/8, $0x00ffffffffffffff +GLOBL ·andMask<>(SB), RODATA|NOPTR, $240 + +DATA ·avx2InitMask<>+0(SB)/8, $0x0000000000000000 +DATA ·avx2InitMask<>+8(SB)/8, $0x0000000000000000 +DATA ·avx2InitMask<>+16(SB)/8, $0x0000000000000001 +DATA ·avx2InitMask<>+24(SB)/8, $0x0000000000000000 +GLOBL ·avx2InitMask<>(SB), RODATA|NOPTR, $32 + +DATA ·rol16<>+0(SB)/8, $0x0504070601000302 +DATA ·rol16<>+8(SB)/8, $0x0d0c0f0e09080b0a +DATA ·rol16<>+16(SB)/8, $0x0504070601000302 +DATA ·rol16<>+24(SB)/8, $0x0d0c0f0e09080b0a +GLOBL ·rol16<>(SB), RODATA|NOPTR, $32 + +DATA ·rol8<>+0(SB)/8, $0x0605040702010003 +DATA ·rol8<>+8(SB)/8, $0x0e0d0c0f0a09080b +DATA ·rol8<>+16(SB)/8, $0x0605040702010003 +DATA ·rol8<>+24(SB)/8, $0x0e0d0c0f0a09080b +GLOBL ·rol8<>(SB), RODATA|NOPTR, $32 + +DATA ·avx2IncMask<>+0(SB)/8, $0x0000000000000002 +DATA ·avx2IncMask<>+8(SB)/8, $0x0000000000000000 +DATA ·avx2IncMask<>+16(SB)/8, $0x0000000000000002 +DATA ·avx2IncMask<>+24(SB)/8, $0x0000000000000000 +GLOBL ·avx2IncMask<>(SB), RODATA|NOPTR, $32 + +// func chacha20Poly1305Seal(dst []byte, key []uint32, src []byte, ad []byte) +// Requires: AVX, AVX2, BMI2, CMOV, SSE2 +TEXT ·chacha20Poly1305Seal(SB), $288-96 + MOVQ SP, BP + ADDQ $0x20, BP + ANDQ $-32, BP + MOVQ dst_base+0(FP), DI + MOVQ key_base+24(FP), R8 + MOVQ src_base+48(FP), SI + MOVQ src_len+56(FP), BX + MOVQ ad_base+72(FP), CX + CMPB ·useAVX2+0(SB), $0x01 + JE chacha20Poly1305Seal_AVX2 + + // Special optimization, for very short buffers + CMPQ BX, $0x80 + JBE sealSSE128 + + // In the seal case - prepare the poly key + 3 blocks of stream in the first iteration + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + + // Store state on stack for future use + MOVO X3, 32(BP) + MOVO X6, 48(BP) + + // Load state, increment counter blocks + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 + + // Store counters + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + MOVQ $0x0000000a, R9 + +sealSSEIntroLoop: + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ R9 + JNE sealSSEIntroLoop + + // Add in the state + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + + // Clamp and store the key + PAND ·polyClampMask<>+0(SB), X0 + MOVO X0, (BP) + MOVO X3, 16(BP) + + // Hash AAD + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, (DI) + MOVOU X4, 16(DI) + MOVOU X7, 32(DI) + MOVOU X10, 48(DI) + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 64(DI) + MOVOU X5, 80(DI) + MOVOU X8, 96(DI) + MOVOU X11, 112(DI) + MOVQ $0x00000080, CX + SUBQ $0x80, BX + LEAQ 128(SI), SI + MOVO X12, X1 + MOVO X13, X4 + MOVO X14, X7 + MOVO X15, X10 + CMPQ BX, $0x40 + JBE sealSSE128SealHash + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X12 + PXOR X3, X13 + PXOR X6, X14 + PXOR X9, X15 + MOVOU X12, 128(DI) + MOVOU X13, 144(DI) + MOVOU X14, 160(DI) + MOVOU X15, 176(DI) + ADDQ $0x40, CX + SUBQ $0x40, BX + LEAQ 64(SI), SI + MOVQ $0x00000002, CX + MOVQ $0x00000008, R9 + CMPQ BX, $0x40 + JBE sealSSETail64 + CMPQ BX, $0x80 + JBE sealSSETail128 + CMPQ BX, $0xc0 + JBE sealSSETail192 + +sealSSEMainLoop: + // Load state, increment counter blocks + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X2, X12 + MOVO X5, X13 + MOVO X8, X14 + MOVO X11, X15 + PADDL ·sseIncMask<>+0(SB), X15 + + // Store counters + MOVO X9, 80(BP) + MOVO X10, 96(BP) + MOVO X11, 112(BP) + MOVO X15, 128(BP) + +sealSSEInnerLoop: + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x0c + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + LEAQ 16(DI), DI + MOVO X14, 64(BP) + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X3 + PXOR X14, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X14) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X3 + PXOR X14, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X4 + PXOR X14, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X14) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X4 + PXOR X14, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x0c, X14 + PSRLL $0x14, X5 + PXOR X14, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X14) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X14 + PSLLL $0x07, X14 + PSRLL $0x19, X5 + PXOR X14, X5 + MOVO 64(BP), X14 + MOVO X7, 64(BP) + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + PADDD X13, X12 + PXOR X12, X15 + ROL16(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x0c, X7 + PSRLL $0x14, X13 + PXOR X7, X13 + PADDD X13, X12 + PXOR X12, X15 + ROL8(X15, X7) + PADDD X15, X14 + PXOR X14, X13 + MOVO X13, X7 + PSLLL $0x07, X7 + PSRLL $0x19, X13 + PXOR X7, X13 + MOVO 64(BP), X7 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x04 + DECQ R9 + JGE sealSSEInnerLoop + ADDQ (DI), R10 + ADCQ 8(DI), R11 ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 IMULQ R12, R15 - MULXQ R11, AX, DX ADDQ AX, R14 ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 ADCQ DX, R8 MOVQ R13, R10 MOVQ R14, R11 @@ -1744,190 +5677,323 @@ openAVX2Tail384LoopB: ADDQ R15, R10 ADCQ R8, R11 ADCQ $0x00, R12 - LEAQ 16(BX), BX - -openAVX2Tail384LoopA: - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x0c, Y14, Y3 - VPSRLD $0x14, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x07, Y14, Y3 - VPSRLD $0x19, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPADDD Y9, Y5, Y5 - VPXOR Y5, Y1, Y1 - VPSHUFB ·rol16<>+0(SB), Y1, Y1 - VPADDD Y1, Y13, Y13 - VPXOR Y13, Y9, Y9 - VPSLLD $0x0c, Y9, Y3 - VPSRLD $0x14, Y9, Y9 - VPXOR Y3, Y9, Y9 - VPADDD Y9, Y5, Y5 - VPXOR Y5, Y1, Y1 - VPSHUFB ·rol8<>+0(SB), Y1, Y1 - VPADDD Y1, Y13, Y13 - VPXOR Y13, Y9, Y9 - VPSLLD $0x07, Y9, Y3 - VPSRLD $0x19, Y9, Y9 - VPXOR Y3, Y9, Y9 - VPADDD Y10, Y6, Y6 - VPXOR Y6, Y2, Y2 - VPSHUFB ·rol16<>+0(SB), Y2, Y2 - VPADDD Y2, Y8, Y8 - VPXOR Y8, Y10, Y10 - VPSLLD $0x0c, Y10, Y3 - VPSRLD $0x14, Y10, Y10 - VPXOR Y3, Y10, Y10 - VPADDD Y10, Y6, Y6 - VPXOR Y6, Y2, Y2 - VPSHUFB ·rol8<>+0(SB), Y2, Y2 - VPADDD Y2, Y8, Y8 - VPXOR Y8, Y10, Y10 - VPSLLD $0x07, Y10, Y3 - VPSRLD $0x19, Y10, Y10 - VPXOR Y3, Y10, Y10 - VPALIGNR $0x04, Y14, Y14, Y14 - VPALIGNR $0x04, Y9, Y9, Y9 - VPALIGNR $0x04, Y10, Y10, Y10 - VPALIGNR $0x08, Y12, Y12, Y12 - VPALIGNR $0x08, Y13, Y13, Y13 - VPALIGNR $0x08, Y8, Y8, Y8 - VPALIGNR $0x0c, Y4, Y4, Y4 - VPALIGNR $0x0c, Y1, Y1, Y1 - VPALIGNR $0x0c, Y2, Y2, Y2 - ADDQ (BX), R10 - ADCQ 8(BX), R11 - ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 - IMULQ R12, R15 - MULXQ R11, AX, DX - ADDQ AX, R14 - ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX - ADDQ AX, R15 - ADCQ DX, R8 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - LEAQ 16(BX), BX - INCQ R9 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x0c, Y14, Y3 - VPSRLD $0x14, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPADDD Y14, Y0, Y0 - VPXOR Y0, Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPADDD Y4, Y12, Y12 - VPXOR Y12, Y14, Y14 - VPSLLD $0x07, Y14, Y3 - VPSRLD $0x19, Y14, Y14 - VPXOR Y3, Y14, Y14 - VPADDD Y9, Y5, Y5 - VPXOR Y5, Y1, Y1 - VPSHUFB ·rol16<>+0(SB), Y1, Y1 - VPADDD Y1, Y13, Y13 - VPXOR Y13, Y9, Y9 - VPSLLD $0x0c, Y9, Y3 - VPSRLD $0x14, Y9, Y9 - VPXOR Y3, Y9, Y9 - VPADDD Y9, Y5, Y5 - VPXOR Y5, Y1, Y1 - VPSHUFB ·rol8<>+0(SB), Y1, Y1 - VPADDD Y1, Y13, Y13 - VPXOR Y13, Y9, Y9 - VPSLLD $0x07, Y9, Y3 - VPSRLD $0x19, Y9, Y9 - VPXOR Y3, Y9, Y9 - VPADDD Y10, Y6, Y6 - VPXOR Y6, Y2, Y2 - VPSHUFB ·rol16<>+0(SB), Y2, Y2 - VPADDD Y2, Y8, Y8 - VPXOR Y8, Y10, Y10 - VPSLLD $0x0c, Y10, Y3 - VPSRLD $0x14, Y10, Y10 - VPXOR Y3, Y10, Y10 - VPADDD Y10, Y6, Y6 - VPXOR Y6, Y2, Y2 - VPSHUFB ·rol8<>+0(SB), Y2, Y2 - VPADDD Y2, Y8, Y8 - VPXOR Y8, Y10, Y10 - VPSLLD $0x07, Y10, Y3 - VPSRLD $0x19, Y10, Y10 - VPXOR Y3, Y10, Y10 - VPALIGNR $0x0c, Y14, Y14, Y14 - VPALIGNR $0x0c, Y9, Y9, Y9 - VPALIGNR $0x0c, Y10, Y10, Y10 - VPALIGNR $0x08, Y12, Y12, Y12 - VPALIGNR $0x08, Y13, Y13, Y13 - VPALIGNR $0x08, Y8, Y8, Y8 - VPALIGNR $0x04, Y4, Y4, Y4 - VPALIGNR $0x04, Y1, Y1, Y1 - VPALIGNR $0x04, Y2, Y2, Y2 - CMPQ R9, CX - JB openAVX2Tail384LoopB - CMPQ R9, $0x0a - JNE openAVX2Tail384LoopA - MOVQ BX, R9 - SUBQ SI, BX - MOVQ BX, CX - MOVQ 224(BP), BX + LEAQ 16(DI), DI + DECQ CX + JG sealSSEInnerLoop + + // Add in the state + PADDD ·chacha20Constants<>+0(SB), X0 + PADDD ·chacha20Constants<>+0(SB), X1 + PADDD ·chacha20Constants<>+0(SB), X2 + PADDD ·chacha20Constants<>+0(SB), X12 + PADDD 32(BP), X3 + PADDD 32(BP), X4 + PADDD 32(BP), X5 + PADDD 32(BP), X13 + PADDD 48(BP), X6 + PADDD 48(BP), X7 + PADDD 48(BP), X8 + PADDD 48(BP), X14 + PADDD 80(BP), X9 + PADDD 96(BP), X10 + PADDD 112(BP), X11 + PADDD 128(BP), X15 + MOVO X15, 64(BP) + + // Load - xor - store + MOVOU (SI), X15 + PXOR X15, X0 + MOVOU 16(SI), X15 + PXOR X15, X3 + MOVOU 32(SI), X15 + PXOR X15, X6 + MOVOU 48(SI), X15 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVO 64(BP), X15 + MOVOU 64(SI), X0 + MOVOU 80(SI), X3 + MOVOU 96(SI), X6 + MOVOU 112(SI), X9 + PXOR X0, X1 + PXOR X3, X4 + PXOR X6, X7 + PXOR X9, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVOU 128(SI), X0 + MOVOU 144(SI), X3 + MOVOU 160(SI), X6 + MOVOU 176(SI), X9 + PXOR X0, X2 + PXOR X3, X5 + PXOR X6, X8 + PXOR X9, X11 + MOVOU X2, 128(DI) + MOVOU X5, 144(DI) + MOVOU X8, 160(DI) + MOVOU X11, 176(DI) + ADDQ $0xc0, SI + MOVQ $0x000000c0, CX + SUBQ $0xc0, BX + MOVO X12, X1 + MOVO X13, X4 + MOVO X14, X7 + MOVO X15, X10 + CMPQ BX, $0x40 + JBE sealSSE128SealHash + MOVOU (SI), X0 + MOVOU 16(SI), X3 + MOVOU 32(SI), X6 + MOVOU 48(SI), X9 + PXOR X0, X12 + PXOR X3, X13 + PXOR X6, X14 + PXOR X9, X15 + MOVOU X12, 192(DI) + MOVOU X13, 208(DI) + MOVOU X14, 224(DI) + MOVOU X15, 240(DI) + LEAQ 64(SI), SI + SUBQ $0x40, BX + MOVQ $0x00000006, CX + MOVQ $0x00000004, R9 + CMPQ BX, $0xc0 + JG sealSSEMainLoop + MOVQ BX, CX + TESTQ BX, BX + JE sealSSE128SealHash + MOVQ $0x00000006, CX + CMPQ BX, $0x40 + JBE sealSSETail64 + CMPQ BX, $0x80 + JBE sealSSETail128 + JMP sealSSETail192 + +sealSSETail64: + MOVO ·chacha20Constants<>+0(SB), X1 + MOVO 32(BP), X4 + MOVO 48(BP), X7 + MOVO 128(BP), X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 80(BP) + +sealSSETail64LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI -openAVX2Tail384Hash: - ADDQ $0x10, CX - CMPQ CX, BX - JGT openAVX2Tail384HashEnd - ADDQ (R9), R10 - ADCQ 8(R9), R11 +sealSSETail64LoopB: + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x0c, X13 + PSRLL $0x14, X4 + PXOR X13, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x07, X13 + PSRLL $0x19, X4 + PXOR X13, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x0c, X13 + PSRLL $0x14, X4 + PXOR X13, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X13) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X13 + PSLLL $0x07, X13 + PSRLL $0x19, X4 + PXOR X13, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + DECQ CX + JG sealSSETail64LoopA + DECQ R9 + JGE sealSSETail64LoopB + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X4 + PADDL 48(BP), X7 + PADDL 80(BP), X10 + JMP sealSSE128Seal + +sealSSETail128: + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + +sealSSETail128LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 IMULQ R12, R15 - MULXQ R11, AX, DX ADDQ AX, R14 ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 ADCQ DX, R8 MOVQ R13, R10 MOVQ R14, R11 @@ -1944,377 +6010,905 @@ openAVX2Tail384Hash: ADDQ R15, R10 ADCQ R8, R11 ADCQ $0x00, R12 - LEAQ 16(R9), R9 - JMP openAVX2Tail384Hash - -openAVX2Tail384HashEnd: - VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 - VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 - VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 - VPADDD 32(BP), Y14, Y14 - VPADDD 32(BP), Y9, Y9 - VPADDD 32(BP), Y10, Y10 - VPADDD 64(BP), Y12, Y12 - VPADDD 64(BP), Y13, Y13 - VPADDD 64(BP), Y8, Y8 - VPADDD 96(BP), Y4, Y4 - VPADDD 128(BP), Y1, Y1 - VPADDD 160(BP), Y2, Y2 - VPERM2I128 $0x02, Y0, Y14, Y3 - VPERM2I128 $0x02, Y12, Y4, Y7 - VPERM2I128 $0x13, Y0, Y14, Y11 - VPERM2I128 $0x13, Y12, Y4, Y15 - VPXOR (SI), Y3, Y3 - VPXOR 32(SI), Y7, Y7 - VPXOR 64(SI), Y11, Y11 - VPXOR 96(SI), Y15, Y15 - VMOVDQU Y3, (DI) - VMOVDQU Y7, 32(DI) - VMOVDQU Y11, 64(DI) - VMOVDQU Y15, 96(DI) - VPERM2I128 $0x02, Y5, Y9, Y3 - VPERM2I128 $0x02, Y13, Y1, Y7 - VPERM2I128 $0x13, Y5, Y9, Y11 - VPERM2I128 $0x13, Y13, Y1, Y15 - VPXOR 128(SI), Y3, Y3 - VPXOR 160(SI), Y7, Y7 - VPXOR 192(SI), Y11, Y11 - VPXOR 224(SI), Y15, Y15 - VMOVDQU Y3, 128(DI) - VMOVDQU Y7, 160(DI) - VMOVDQU Y11, 192(DI) - VMOVDQU Y15, 224(DI) - VPERM2I128 $0x02, Y6, Y10, Y0 - VPERM2I128 $0x02, Y8, Y2, Y14 - VPERM2I128 $0x13, Y6, Y10, Y12 - VPERM2I128 $0x13, Y8, Y2, Y4 - LEAQ 256(SI), SI - LEAQ 256(DI), DI - SUBQ $0x00000100, BX - JMP openAVX2TailLoop + LEAQ 16(DI), DI -openAVX2Tail512: - VMOVDQU ·chacha20Constants<>+0(SB), Y0 - VMOVDQA Y0, Y5 - VMOVDQA Y0, Y6 - VMOVDQA Y0, Y7 - VMOVDQA 32(BP), Y14 - VMOVDQA Y14, Y9 - VMOVDQA Y14, Y10 - VMOVDQA Y14, Y11 - VMOVDQA 64(BP), Y12 - VMOVDQA Y12, Y13 - VMOVDQA Y12, Y8 - VMOVDQA Y12, Y15 - VMOVDQA 192(BP), Y4 - VPADDD ·avx2IncMask<>+0(SB), Y4, Y4 - VPADDD ·avx2IncMask<>+0(SB), Y4, Y1 - VPADDD ·avx2IncMask<>+0(SB), Y1, Y2 - VPADDD ·avx2IncMask<>+0(SB), Y2, Y3 - VMOVDQA Y4, 96(BP) - VMOVDQA Y1, 128(BP) - VMOVDQA Y2, 160(BP) - VMOVDQA Y3, 192(BP) - XORQ CX, CX - MOVQ SI, R9 +sealSSETail128LoopB: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + DECQ CX + JG sealSSETail128LoopA + DECQ R9 + JGE sealSSETail128LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 80(BP), X9 + PADDL 96(BP), X10 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X0 + PXOR X13, X3 + PXOR X14, X6 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVQ $0x00000040, CX + LEAQ 64(SI), SI + SUBQ $0x40, BX + JMP sealSSE128SealHash + +sealSSETail192: + MOVO ·chacha20Constants<>+0(SB), X0 + MOVO 32(BP), X3 + MOVO 48(BP), X6 + MOVO 128(BP), X9 + PADDL ·sseIncMask<>+0(SB), X9 + MOVO X9, 80(BP) + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X10, 96(BP) + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X11, 112(BP) + +sealSSETail192LoopA: + ADDQ (DI), R10 + ADCQ 8(DI), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI -openAVX2Tail512LoopB: - ADDQ (R9), R10 - ADCQ 8(R9), R11 +sealSSETail192LoopB: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + ADDQ (DI), R10 + ADCQ 8(DI), R11 ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 IMULQ R12, R15 - MULXQ R11, AX, DX ADDQ AX, R14 ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 ADCQ DX, R8 MOVQ R13, R10 MOVQ R14, R11 MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - LEAQ 16(R9), R9 - -openAVX2Tail512LoopA: - VPADDD Y14, Y0, Y0 - VPADDD Y9, Y5, Y5 - VPADDD Y10, Y6, Y6 - VPADDD Y11, Y7, Y7 - VPXOR Y0, Y4, Y4 - VPXOR Y5, Y1, Y1 - VPXOR Y6, Y2, Y2 - VPXOR Y7, Y3, Y3 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y1, Y1 - VPSHUFB ·rol16<>+0(SB), Y2, Y2 - VPSHUFB ·rol16<>+0(SB), Y3, Y3 - VPADDD Y4, Y12, Y12 - VPADDD Y1, Y13, Y13 - VPADDD Y2, Y8, Y8 - VPADDD Y3, Y15, Y15 - VPXOR Y12, Y14, Y14 - VPXOR Y13, Y9, Y9 - VPXOR Y8, Y10, Y10 - VPXOR Y15, Y11, Y11 - VMOVDQA Y15, 224(BP) - VPSLLD $0x0c, Y14, Y15 - VPSRLD $0x14, Y14, Y14 - VPXOR Y15, Y14, Y14 - VPSLLD $0x0c, Y9, Y15 - VPSRLD $0x14, Y9, Y9 - VPXOR Y15, Y9, Y9 - VPSLLD $0x0c, Y10, Y15 - VPSRLD $0x14, Y10, Y10 - VPXOR Y15, Y10, Y10 - VPSLLD $0x0c, Y11, Y15 - VPSRLD $0x14, Y11, Y11 - VPXOR Y15, Y11, Y11 - VMOVDQA 224(BP), Y15 - ADDQ (R9), R10 - ADCQ 8(R9), R11 - ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 - IMULQ R12, R15 - MULXQ R11, AX, DX - ADDQ AX, R14 - ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX - ADDQ AX, R15 - ADCQ DX, R8 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - VPADDD Y14, Y0, Y0 - VPADDD Y9, Y5, Y5 - VPADDD Y10, Y6, Y6 - VPADDD Y11, Y7, Y7 - VPXOR Y0, Y4, Y4 - VPXOR Y5, Y1, Y1 - VPXOR Y6, Y2, Y2 - VPXOR Y7, Y3, Y3 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y1, Y1 - VPSHUFB ·rol8<>+0(SB), Y2, Y2 - VPSHUFB ·rol8<>+0(SB), Y3, Y3 - VPADDD Y4, Y12, Y12 - VPADDD Y1, Y13, Y13 - VPADDD Y2, Y8, Y8 - VPADDD Y3, Y15, Y15 - VPXOR Y12, Y14, Y14 - VPXOR Y13, Y9, Y9 - VPXOR Y8, Y10, Y10 - VPXOR Y15, Y11, Y11 - VMOVDQA Y15, 224(BP) - VPSLLD $0x07, Y14, Y15 - VPSRLD $0x19, Y14, Y14 - VPXOR Y15, Y14, Y14 - VPSLLD $0x07, Y9, Y15 - VPSRLD $0x19, Y9, Y9 - VPXOR Y15, Y9, Y9 - VPSLLD $0x07, Y10, Y15 - VPSRLD $0x19, Y10, Y10 - VPXOR Y15, Y10, Y10 - VPSLLD $0x07, Y11, Y15 - VPSRLD $0x19, Y11, Y11 - VPXOR Y15, Y11, Y11 - VMOVDQA 224(BP), Y15 - VPALIGNR $0x04, Y14, Y14, Y14 - VPALIGNR $0x04, Y9, Y9, Y9 - VPALIGNR $0x04, Y10, Y10, Y10 - VPALIGNR $0x04, Y11, Y11, Y11 - VPALIGNR $0x08, Y12, Y12, Y12 - VPALIGNR $0x08, Y13, Y13, Y13 - VPALIGNR $0x08, Y8, Y8, Y8 - VPALIGNR $0x08, Y15, Y15, Y15 - VPALIGNR $0x0c, Y4, Y4, Y4 - VPALIGNR $0x0c, Y1, Y1, Y1 - VPALIGNR $0x0c, Y2, Y2, Y2 - VPALIGNR $0x0c, Y3, Y3, Y3 - VPADDD Y14, Y0, Y0 - VPADDD Y9, Y5, Y5 - VPADDD Y10, Y6, Y6 - VPADDD Y11, Y7, Y7 - VPXOR Y0, Y4, Y4 - VPXOR Y5, Y1, Y1 - VPXOR Y6, Y2, Y2 - VPXOR Y7, Y3, Y3 - VPSHUFB ·rol16<>+0(SB), Y4, Y4 - VPSHUFB ·rol16<>+0(SB), Y1, Y1 - VPSHUFB ·rol16<>+0(SB), Y2, Y2 - VPSHUFB ·rol16<>+0(SB), Y3, Y3 - VPADDD Y4, Y12, Y12 - VPADDD Y1, Y13, Y13 - VPADDD Y2, Y8, Y8 - VPADDD Y3, Y15, Y15 - VPXOR Y12, Y14, Y14 - VPXOR Y13, Y9, Y9 - VPXOR Y8, Y10, Y10 - VPXOR Y15, Y11, Y11 - ADDQ 16(R9), R10 - ADCQ 24(R9), R11 - ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 - IMULQ R12, R15 - MULXQ R11, AX, DX - ADDQ AX, R14 - ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX - ADDQ AX, R15 - ADCQ DX, R8 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - LEAQ 32(R9), R9 - VMOVDQA Y15, 224(BP) - VPSLLD $0x0c, Y14, Y15 - VPSRLD $0x14, Y14, Y14 - VPXOR Y15, Y14, Y14 - VPSLLD $0x0c, Y9, Y15 - VPSRLD $0x14, Y9, Y9 - VPXOR Y15, Y9, Y9 - VPSLLD $0x0c, Y10, Y15 - VPSRLD $0x14, Y10, Y10 - VPXOR Y15, Y10, Y10 - VPSLLD $0x0c, Y11, Y15 - VPSRLD $0x14, Y11, Y11 - VPXOR Y15, Y11, Y11 - VMOVDQA 224(BP), Y15 - VPADDD Y14, Y0, Y0 - VPADDD Y9, Y5, Y5 - VPADDD Y10, Y6, Y6 - VPADDD Y11, Y7, Y7 - VPXOR Y0, Y4, Y4 - VPXOR Y5, Y1, Y1 - VPXOR Y6, Y2, Y2 - VPXOR Y7, Y3, Y3 - VPSHUFB ·rol8<>+0(SB), Y4, Y4 - VPSHUFB ·rol8<>+0(SB), Y1, Y1 - VPSHUFB ·rol8<>+0(SB), Y2, Y2 - VPSHUFB ·rol8<>+0(SB), Y3, Y3 - VPADDD Y4, Y12, Y12 - VPADDD Y1, Y13, Y13 - VPADDD Y2, Y8, Y8 - VPADDD Y3, Y15, Y15 - VPXOR Y12, Y14, Y14 - VPXOR Y13, Y9, Y9 - VPXOR Y8, Y10, Y10 - VPXOR Y15, Y11, Y11 - VMOVDQA Y15, 224(BP) - VPSLLD $0x07, Y14, Y15 - VPSRLD $0x19, Y14, Y14 - VPXOR Y15, Y14, Y14 - VPSLLD $0x07, Y9, Y15 - VPSRLD $0x19, Y9, Y9 - VPXOR Y15, Y9, Y9 - VPSLLD $0x07, Y10, Y15 - VPSRLD $0x19, Y10, Y10 - VPXOR Y15, Y10, Y10 - VPSLLD $0x07, Y11, Y15 - VPSRLD $0x19, Y11, Y11 - VPXOR Y15, Y11, Y11 - VMOVDQA 224(BP), Y15 - VPALIGNR $0x0c, Y14, Y14, Y14 - VPALIGNR $0x0c, Y9, Y9, Y9 - VPALIGNR $0x0c, Y10, Y10, Y10 - VPALIGNR $0x0c, Y11, Y11, Y11 - VPALIGNR $0x08, Y12, Y12, Y12 - VPALIGNR $0x08, Y13, Y13, Y13 - VPALIGNR $0x08, Y8, Y8, Y8 - VPALIGNR $0x08, Y15, Y15, Y15 - VPALIGNR $0x04, Y4, Y4, Y4 - VPALIGNR $0x04, Y1, Y1, Y1 - VPALIGNR $0x04, Y2, Y2, Y2 - VPALIGNR $0x04, Y3, Y3, Y3 - INCQ CX - CMPQ CX, $0x04 - JLT openAVX2Tail512LoopB - CMPQ CX, $0x0a - JNE openAVX2Tail512LoopA - MOVQ BX, CX - SUBQ $0x00000180, CX - ANDQ $-16, CX + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + LEAQ 16(DI), DI + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ CX + JG sealSSETail192LoopA + DECQ R9 + JGE sealSSETail192LoopB + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL 32(BP), X3 + PADDL 32(BP), X4 + PADDL 32(BP), X5 + PADDL 48(BP), X6 + PADDL 48(BP), X7 + PADDL 48(BP), X8 + PADDL 80(BP), X9 + PADDL 96(BP), X10 + PADDL 112(BP), X11 + MOVOU (SI), X12 + MOVOU 16(SI), X13 + MOVOU 32(SI), X14 + MOVOU 48(SI), X15 + PXOR X12, X0 + PXOR X13, X3 + PXOR X14, X6 + PXOR X15, X9 + MOVOU X0, (DI) + MOVOU X3, 16(DI) + MOVOU X6, 32(DI) + MOVOU X9, 48(DI) + MOVOU 64(SI), X12 + MOVOU 80(SI), X13 + MOVOU 96(SI), X14 + MOVOU 112(SI), X15 + PXOR X12, X1 + PXOR X13, X4 + PXOR X14, X7 + PXOR X15, X10 + MOVOU X1, 64(DI) + MOVOU X4, 80(DI) + MOVOU X7, 96(DI) + MOVOU X10, 112(DI) + MOVO X2, X1 + MOVO X5, X4 + MOVO X8, X7 + MOVO X11, X10 + MOVQ $0x00000080, CX + LEAQ 128(SI), SI + SUBQ $0x80, BX + JMP sealSSE128SealHash + +sealSSE128: + MOVOU ·chacha20Constants<>+0(SB), X0 + MOVOU 16(R8), X3 + MOVOU 32(R8), X6 + MOVOU 48(R8), X9 + MOVO X0, X1 + MOVO X3, X4 + MOVO X6, X7 + MOVO X9, X10 + PADDL ·sseIncMask<>+0(SB), X10 + MOVO X1, X2 + MOVO X4, X5 + MOVO X7, X8 + MOVO X10, X11 + PADDL ·sseIncMask<>+0(SB), X11 + MOVO X3, X13 + MOVO X6, X14 + MOVO X10, X15 + MOVQ $0x0000000a, R9 + +sealSSE128InnerCipherLoop: + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x04 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x0c + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + PADDD X3, X0 + PXOR X0, X9 + ROL16(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X3 + PXOR X12, X3 + PADDD X3, X0 + PXOR X0, X9 + ROL8(X9, X12) + PADDD X9, X6 + PXOR X6, X3 + MOVO X3, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X3 + PXOR X12, X3 + PADDD X4, X1 + PXOR X1, X10 + ROL16(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X4 + PXOR X12, X4 + PADDD X4, X1 + PXOR X1, X10 + ROL8(X10, X12) + PADDD X10, X7 + PXOR X7, X4 + MOVO X4, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X4 + PXOR X12, X4 + PADDD X5, X2 + PXOR X2, X11 + ROL16(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x0c, X12 + PSRLL $0x14, X5 + PXOR X12, X5 + PADDD X5, X2 + PXOR X2, X11 + ROL8(X11, X12) + PADDD X11, X8 + PXOR X8, X5 + MOVO X5, X12 + PSLLL $0x07, X12 + PSRLL $0x19, X5 + PXOR X12, X5 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xe4 + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xed + BYTE $0x0c + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xf6 + BYTE $0x08 + BYTE $0x66 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xff + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc0 + BYTE $0x08 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xc9 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xd2 + BYTE $0x04 + BYTE $0x66 + BYTE $0x45 + BYTE $0x0f + BYTE $0x3a + BYTE $0x0f + BYTE $0xdb + BYTE $0x04 + DECQ R9 + JNE sealSSE128InnerCipherLoop + + // A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded + PADDL ·chacha20Constants<>+0(SB), X0 + PADDL ·chacha20Constants<>+0(SB), X1 + PADDL ·chacha20Constants<>+0(SB), X2 + PADDL X13, X3 + PADDL X13, X4 + PADDL X13, X5 + PADDL X14, X7 + PADDL X14, X8 + PADDL X15, X10 + PADDL ·sseIncMask<>+0(SB), X15 + PADDL X15, X11 + PAND ·polyClampMask<>+0(SB), X0 + MOVOU X0, (BP) + MOVOU X3, 16(BP) -openAVX2Tail512HashLoop: - TESTQ CX, CX - JE openAVX2Tail512HashEnd - ADDQ (R9), R10 - ADCQ 8(R9), R11 + // Hash + MOVQ ad_len+80(FP), R9 + CALL polyHashADInternal<>(SB) + XORQ CX, CX + +sealSSE128SealHash: + CMPQ CX, $0x10 + JB sealSSE128Seal + ADDQ (DI), R10 + ADCQ 8(DI), R11 ADCQ $0x01, R12 - MOVQ (BP), DX - MOVQ DX, R15 - MULXQ R10, R13, R14 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 IMULQ R12, R15 - MULXQ R11, AX, DX ADDQ AX, R14 ADCQ DX, R15 - MOVQ 8(BP), DX - MULXQ R10, R10, AX - ADDQ R10, R14 - MULXQ R11, R11, R8 - ADCQ R11, R15 - ADCQ $0x00, R8 - IMULQ R12, DX + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 ADCQ DX, R8 MOVQ R13, R10 MOVQ R14, R11 @@ -2331,162 +6925,238 @@ openAVX2Tail512HashLoop: ADDQ R15, R10 ADCQ R8, R11 ADCQ $0x00, R12 - LEAQ 16(R9), R9 SUBQ $0x10, CX - JMP openAVX2Tail512HashLoop + ADDQ $0x10, DI + JMP sealSSE128SealHash -openAVX2Tail512HashEnd: - VPADDD ·chacha20Constants<>+0(SB), Y0, Y0 - VPADDD ·chacha20Constants<>+0(SB), Y5, Y5 - VPADDD ·chacha20Constants<>+0(SB), Y6, Y6 - VPADDD ·chacha20Constants<>+0(SB), Y7, Y7 - VPADDD 32(BP), Y14, Y14 - VPADDD 32(BP), Y9, Y9 - VPADDD 32(BP), Y10, Y10 - VPADDD 32(BP), Y11, Y11 - VPADDD 64(BP), Y12, Y12 - VPADDD 64(BP), Y13, Y13 - VPADDD 64(BP), Y8, Y8 - VPADDD 64(BP), Y15, Y15 - VPADDD 96(BP), Y4, Y4 - VPADDD 128(BP), Y1, Y1 - VPADDD 160(BP), Y2, Y2 - VPADDD 192(BP), Y3, Y3 - VMOVDQA Y15, 224(BP) - VPERM2I128 $0x02, Y0, Y14, Y15 - VPERM2I128 $0x13, Y0, Y14, Y14 - VPERM2I128 $0x02, Y12, Y4, Y0 - VPERM2I128 $0x13, Y12, Y4, Y12 - VPXOR (SI), Y15, Y15 - VPXOR 32(SI), Y0, Y0 - VPXOR 64(SI), Y14, Y14 - VPXOR 96(SI), Y12, Y12 - VMOVDQU Y15, (DI) - VMOVDQU Y0, 32(DI) - VMOVDQU Y14, 64(DI) - VMOVDQU Y12, 96(DI) - VPERM2I128 $0x02, Y5, Y9, Y0 - VPERM2I128 $0x02, Y13, Y1, Y14 - VPERM2I128 $0x13, Y5, Y9, Y12 - VPERM2I128 $0x13, Y13, Y1, Y4 - VPXOR 128(SI), Y0, Y0 - VPXOR 160(SI), Y14, Y14 - VPXOR 192(SI), Y12, Y12 - VPXOR 224(SI), Y4, Y4 - VMOVDQU Y0, 128(DI) - VMOVDQU Y14, 160(DI) - VMOVDQU Y12, 192(DI) - VMOVDQU Y4, 224(DI) - VPERM2I128 $0x02, Y6, Y10, Y0 - VPERM2I128 $0x02, Y8, Y2, Y14 - VPERM2I128 $0x13, Y6, Y10, Y12 - VPERM2I128 $0x13, Y8, Y2, Y4 - VPXOR 256(SI), Y0, Y0 - VPXOR 288(SI), Y14, Y14 - VPXOR 320(SI), Y12, Y12 - VPXOR 352(SI), Y4, Y4 - VMOVDQU Y0, 256(DI) - VMOVDQU Y14, 288(DI) - VMOVDQU Y12, 320(DI) - VMOVDQU Y4, 352(DI) - VPERM2I128 $0x02, Y7, Y11, Y0 - VPERM2I128 $0x02, 224(BP), Y3, Y14 - VPERM2I128 $0x13, Y7, Y11, Y12 - VPERM2I128 $0x13, 224(BP), Y3, Y4 - LEAQ 384(SI), SI - LEAQ 384(DI), DI - SUBQ $0x00000180, BX - JMP openAVX2TailLoop +sealSSE128Seal: + CMPQ BX, $0x10 + JB sealSSETail + SUBQ $0x10, BX -DATA ·chacha20Constants<>+0(SB)/4, $0x61707865 -DATA ·chacha20Constants<>+4(SB)/4, $0x3320646e -DATA ·chacha20Constants<>+8(SB)/4, $0x79622d32 -DATA ·chacha20Constants<>+12(SB)/4, $0x6b206574 -DATA ·chacha20Constants<>+16(SB)/4, $0x61707865 -DATA ·chacha20Constants<>+20(SB)/4, $0x3320646e -DATA ·chacha20Constants<>+24(SB)/4, $0x79622d32 -DATA ·chacha20Constants<>+28(SB)/4, $0x6b206574 -GLOBL ·chacha20Constants<>(SB), RODATA|NOPTR, $32 + // Load for decryption + MOVOU (SI), X12 + PXOR X12, X1 + MOVOU X1, (DI) + LEAQ 16(SI), SI + LEAQ 16(DI), DI -DATA ·avx2InitMask<>+0(SB)/8, $0x0000000000000000 -DATA ·avx2InitMask<>+8(SB)/8, $0x0000000000000000 -DATA ·avx2InitMask<>+16(SB)/8, $0x0000000000000001 -DATA ·avx2InitMask<>+24(SB)/8, $0x0000000000000000 -GLOBL ·avx2InitMask<>(SB), RODATA|NOPTR, $32 + // Extract for hashing + MOVQ X1, R13 + PSRLDQ $0x08, X1 + MOVQ X1, R14 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 -DATA ·rol16<>+0(SB)/8, $0x0504070601000302 -DATA ·rol16<>+8(SB)/8, $0x0d0c0f0e09080b0a -DATA ·rol16<>+16(SB)/8, $0x0504070601000302 -DATA ·rol16<>+24(SB)/8, $0x0d0c0f0e09080b0a -GLOBL ·rol16<>(SB), RODATA|NOPTR, $32 + // Shift the stream "left" + MOVO X4, X1 + MOVO X7, X4 + MOVO X10, X7 + MOVO X2, X10 + MOVO X5, X2 + MOVO X8, X5 + MOVO X11, X8 + JMP sealSSE128Seal + +sealSSETail: + TESTQ BX, BX + JE sealSSEFinalize + + // We can only load the PT one byte at a time to avoid read after end of buffer + MOVQ BX, R9 + SHLQ $0x04, R9 + LEAQ ·andMask<>+0(SB), R13 + MOVQ BX, CX + LEAQ -1(SI)(BX*1), SI + XORQ R15, R15 + XORQ R8, R8 + XORQ AX, AX + +sealSSETailLoadLoop: + SHLQ $0x08, R15, R8 + SHLQ $0x08, R15 + MOVB (SI), AX + XORQ AX, R15 + LEAQ -1(SI), SI + DECQ CX + JNE sealSSETailLoadLoop + MOVQ R15, 64(BP) + MOVQ R8, 72(BP) + PXOR 64(BP), X1 + MOVOU X1, (DI) + MOVOU -16(R13)(R9*1), X12 + PAND X12, X1 + MOVQ X1, R13 + PSRLDQ $0x08, X1 + MOVQ X1, R14 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 + ADDQ BX, DI -DATA ·rol8<>+0(SB)/8, $0x0605040702010003 -DATA ·rol8<>+8(SB)/8, $0x0e0d0c0f0a09080b -DATA ·rol8<>+16(SB)/8, $0x0605040702010003 -DATA ·rol8<>+24(SB)/8, $0x0e0d0c0f0a09080b -GLOBL ·rol8<>(SB), RODATA|NOPTR, $32 +sealSSEFinalize: + // Hash in the buffer lengths + ADDQ ad_len+80(FP), R10 + ADCQ src_len+56(FP), R11 + ADCQ $0x01, R12 + MOVQ (BP), AX + MOVQ AX, R15 + MULQ R10 + MOVQ AX, R13 + MOVQ DX, R14 + MOVQ (BP), AX + MULQ R11 + IMULQ R12, R15 + ADDQ AX, R14 + ADCQ DX, R15 + MOVQ 8(BP), AX + MOVQ AX, R8 + MULQ R10 + ADDQ AX, R14 + ADCQ $0x00, DX + MOVQ DX, R10 + MOVQ 8(BP), AX + MULQ R11 + ADDQ AX, R15 + ADCQ $0x00, DX + IMULQ R12, R8 + ADDQ R10, R15 + ADCQ DX, R8 + MOVQ R13, R10 + MOVQ R14, R11 + MOVQ R15, R12 + ANDQ $0x03, R12 + MOVQ R15, R13 + ANDQ $-4, R13 + MOVQ R8, R14 + SHRQ $0x02, R8, R15 + SHRQ $0x02, R8 + ADDQ R13, R10 + ADCQ R14, R11 + ADCQ $0x00, R12 + ADDQ R15, R10 + ADCQ R8, R11 + ADCQ $0x00, R12 -DATA ·polyClampMask<>+0(SB)/8, $0x0ffffffc0fffffff -DATA ·polyClampMask<>+8(SB)/8, $0x0ffffffc0ffffffc -DATA ·polyClampMask<>+16(SB)/8, $0xffffffffffffffff -DATA ·polyClampMask<>+24(SB)/8, $0xffffffffffffffff -GLOBL ·polyClampMask<>(SB), RODATA|NOPTR, $32 + // Final reduce + MOVQ R10, R13 + MOVQ R11, R14 + MOVQ R12, R15 + SUBQ $-5, R10 + SBBQ $-1, R11 + SBBQ $0x03, R12 + CMOVQCS R13, R10 + CMOVQCS R14, R11 + CMOVQCS R15, R12 -DATA ·avx2IncMask<>+0(SB)/8, $0x0000000000000002 -DATA ·avx2IncMask<>+8(SB)/8, $0x0000000000000000 -DATA ·avx2IncMask<>+16(SB)/8, $0x0000000000000002 -DATA ·avx2IncMask<>+24(SB)/8, $0x0000000000000000 -GLOBL ·avx2IncMask<>(SB), RODATA|NOPTR, $32 + // Add in the "s" part of the key + ADDQ 16(BP), R10 + ADCQ 24(BP), R11 -DATA ·andMask<>+0(SB)/8, $0x00000000000000ff -DATA ·andMask<>+8(SB)/8, $0x0000000000000000 -DATA ·andMask<>+16(SB)/8, $0x000000000000ffff -DATA ·andMask<>+24(SB)/8, $0x0000000000000000 -DATA ·andMask<>+32(SB)/8, $0x0000000000ffffff -DATA ·andMask<>+40(SB)/8, $0x0000000000000000 -DATA ·andMask<>+48(SB)/8, $0x00000000ffffffff -DATA ·andMask<>+56(SB)/8, $0x0000000000000000 -DATA ·andMask<>+64(SB)/8, $0x000000ffffffffff -DATA ·andMask<>+72(SB)/8, $0x0000000000000000 -DATA ·andMask<>+80(SB)/8, $0x0000ffffffffffff -DATA ·andMask<>+88(SB)/8, $0x0000000000000000 -DATA ·andMask<>+96(SB)/8, $0x00ffffffffffffff -DATA ·andMask<>+104(SB)/8, $0x0000000000000000 -DATA ·andMask<>+112(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+120(SB)/8, $0x0000000000000000 -DATA ·andMask<>+128(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+136(SB)/8, $0x00000000000000ff -DATA ·andMask<>+144(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+152(SB)/8, $0x000000000000ffff -DATA ·andMask<>+160(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+168(SB)/8, $0x0000000000ffffff -DATA ·andMask<>+176(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+184(SB)/8, $0x00000000ffffffff -DATA ·andMask<>+192(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+200(SB)/8, $0x000000ffffffffff -DATA ·andMask<>+208(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+216(SB)/8, $0x0000ffffffffffff -DATA ·andMask<>+224(SB)/8, $0xffffffffffffffff -DATA ·andMask<>+232(SB)/8, $0x00ffffffffffffff -GLOBL ·andMask<>(SB), RODATA|NOPTR, $240 + // Finally store the tag at the end of the message + MOVQ R10, (DI) + MOVQ R11, 8(DI) + RET -// func chacha20Poly1305Seal(dst []byte, key []uint32, src []byte, ad []byte) -// Requires: AVX, AVX2, BMI2, CMOV, SSE2 -TEXT ·chacha20Poly1305Seal(SB), $288-96 - MOVQ SP, BP - ADDQ $0x20, BP - ANDQ $-32, BP - MOVQ dst_base+0(FP), DI - MOVQ key_base+24(FP), R8 - MOVQ src_base+48(FP), SI - MOVQ src_len+56(FP), BX - MOVQ ad_base+72(FP), CX +chacha20Poly1305Seal_AVX2: VZEROUPPER - VMOVDQU ·chacha20Constants<>+0(SB), Y0 - VBROADCASTI128 16(R8), Y14 - VBROADCASTI128 32(R8), Y12 - VBROADCASTI128 48(R8), Y4 - VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 + VMOVDQU ·chacha20Constants<>+0(SB), Y0 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x70 + BYTE $0x10 + BYTE $0xc4 + BYTE $0x42 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x20 + BYTE $0xc4 + BYTE $0xc2 + BYTE $0x7d + BYTE $0x5a + BYTE $0x60 + BYTE $0x30 + VPADDD ·avx2InitMask<>+0(SB), Y4, Y4 // Special optimizations, for very short buffers CMPQ BX, $0x000000c0 @@ -3500,144 +8170,6 @@ sealAVX2InternalLoopStart: JBE sealAVX2Tail384 JMP sealAVX2Tail512 -sealSSETail: - TESTQ BX, BX - JE sealSSEFinalize - - // We can only load the PT one byte at a time to avoid read after end of buffer - MOVQ BX, R9 - SHLQ $0x04, R9 - LEAQ ·andMask<>+0(SB), R13 - MOVQ BX, CX - LEAQ -1(SI)(BX*1), SI - XORQ R15, R15 - XORQ R8, R8 - XORQ AX, AX - -sealSSETailLoadLoop: - SHLQ $0x08, R15, R8 - SHLQ $0x08, R15 - MOVB (SI), AX - XORQ AX, R15 - LEAQ -1(SI), SI - DECQ CX - JNE sealSSETailLoadLoop - MOVQ R15, 64(BP) - MOVQ R8, 72(BP) - PXOR 64(BP), X1 - MOVOU X1, (DI) - MOVOU -16(R13)(R9*1), X12 - PAND X12, X1 - MOVQ X1, R13 - PSRLDQ $0x08, X1 - MOVQ X1, R14 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x01, R12 - MOVQ (BP), AX - MOVQ AX, R15 - MULQ R10 - MOVQ AX, R13 - MOVQ DX, R14 - MOVQ (BP), AX - MULQ R11 - IMULQ R12, R15 - ADDQ AX, R14 - ADCQ DX, R15 - MOVQ 8(BP), AX - MOVQ AX, R8 - MULQ R10 - ADDQ AX, R14 - ADCQ $0x00, DX - MOVQ DX, R10 - MOVQ 8(BP), AX - MULQ R11 - ADDQ AX, R15 - ADCQ $0x00, DX - IMULQ R12, R8 - ADDQ R10, R15 - ADCQ DX, R8 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - ADDQ BX, DI - -sealSSEFinalize: - // Hash in the buffer lengths - ADDQ ad_len+80(FP), R10 - ADCQ src_len+56(FP), R11 - ADCQ $0x01, R12 - MOVQ (BP), AX - MOVQ AX, R15 - MULQ R10 - MOVQ AX, R13 - MOVQ DX, R14 - MOVQ (BP), AX - MULQ R11 - IMULQ R12, R15 - ADDQ AX, R14 - ADCQ DX, R15 - MOVQ 8(BP), AX - MOVQ AX, R8 - MULQ R10 - ADDQ AX, R14 - ADCQ $0x00, DX - MOVQ DX, R10 - MOVQ 8(BP), AX - MULQ R11 - ADDQ AX, R15 - ADCQ $0x00, DX - IMULQ R12, R8 - ADDQ R10, R15 - ADCQ DX, R8 - MOVQ R13, R10 - MOVQ R14, R11 - MOVQ R15, R12 - ANDQ $0x03, R12 - MOVQ R15, R13 - ANDQ $-4, R13 - MOVQ R8, R14 - SHRQ $0x02, R8, R15 - SHRQ $0x02, R8 - ADDQ R13, R10 - ADCQ R14, R11 - ADCQ $0x00, R12 - ADDQ R15, R10 - ADCQ R8, R11 - ADCQ $0x00, R12 - - // Final reduce - MOVQ R10, R13 - MOVQ R11, R14 - MOVQ R12, R15 - SUBQ $-5, R10 - SBBQ $-1, R11 - SBBQ $0x03, R12 - CMOVQCS R13, R10 - CMOVQCS R14, R11 - CMOVQCS R15, R12 - - // Add in the "s" part of the key - ADDQ 16(BP), R10 - ADCQ 24(BP), R11 - - // Finally store the tag at the end of the message - MOVQ R10, (DI) - MOVQ R11, 8(DI) - RET - seal192AVX2: VMOVDQA Y0, Y5 VMOVDQA Y14, Y9 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/certs.go b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/certs.go index 6f75d77ec..139fa31e1 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/certs.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/certs.go @@ -348,9 +348,6 @@ func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) if cert.CertType != HostCert { return fmt.Errorf("ssh: certificate presented as a host key has type %d", cert.CertType) } - if c.IsHostAuthority == nil { - return errors.New("ssh: cannot verify certificate, IsHostAuthority not set") - } if !c.IsHostAuthority(cert.SignatureKey, addr) { return fmt.Errorf("ssh: no authorities for hostname: %v", addr) } @@ -378,9 +375,6 @@ func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permis if cert.CertType != UserCert { return nil, fmt.Errorf("ssh: cert has type %d", cert.CertType) } - if c.IsUserAuthority == nil { - return nil, errors.New("ssh: cannot verify certificate, IsUserAuthority not set") - } if !c.IsUserAuthority(cert.SignatureKey) { return nil, fmt.Errorf("ssh: certificate signed by unrecognized authority") } @@ -444,17 +438,7 @@ func (c *CertChecker) CheckCert(principal string, cert *Certificate) error { if before := int64(cert.ValidBefore); cert.ValidBefore != uint64(CertTimeInfinity) && (unixNow >= before || before < 0) { return fmt.Errorf("ssh: cert has expired") } - // Match OpenSSH: the SK user-presence flag is never enforced on a - // certificate's CA signature. OpenSSH calls sshkey_verify with - // detailsp==NULL in sshkey.c:cert_parse, so the UP/UV flags are - // not even extracted. The UP bit on a CA signature reflects the - // CA operator's presence at signing time, which has no bearing on - // whether the user being authenticated is present now; enforcing - // it here would only break interop with certificates issued by - // non-interactive SK CAs. skKeyWithoutUP is a no-op for non-SK - // keys (the common case). - caKey := skKeyWithoutUP(cert.SignatureKey) - if err := caKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { + if err := cert.SignatureKey.Verify(cert.bytesForSigning(), cert.Signature); err != nil { return fmt.Errorf("ssh: certificate signature does not verify") } diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/channel.go b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/channel.go index 67379966b..cc0bb7ab6 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/channel.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/channel.go @@ -11,7 +11,6 @@ import ( "io" "log" "sync" - "sync/atomic" ) const ( @@ -132,17 +131,11 @@ func (r RejectionReason) String() string { return fmt.Sprintf("unknown reason %d", int(r)) } -// minPayloadSize returns min(limit, length) clamped to a uint32. It is used -// to compute the size of the next channel data packet from the remaining -// payload. The comparison is done in int64 because length is an int — on -// 64-bit systems len(data) can exceed 2^32, and a direct uint32(length) -// cast would silently truncate to 0 at every multiple of 2^32, causing -// WriteExtended's loop to spin without making progress. -func minPayloadSize(limit uint32, length int) uint32 { - if int64(length) > int64(limit) { - return limit +func min(a uint32, b int) uint32 { + if a < uint32(b) { + return a } - return uint32(length) + return uint32(b) } type channelDirection uint8 @@ -184,12 +177,6 @@ type channel struct { // with WantReply=true outstanding. This lock is held by a // goroutine that has such an outgoing request pending. sentRequestMu sync.Mutex - // sentRequestPending is set to true while a SendRequest call with - // WantReply=true is in flight. handlePacket uses it as a gate: responses - // arriving while no request is pending are dropped to prevent a - // misbehaving peer from stalling the mux read loop by filling ch.msg - // with unsolicited channelRequestSuccess/Failure messages. - sentRequestPending atomic.Bool incomingRequests chan *Request @@ -264,7 +251,7 @@ func (ch *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err e ch.writeMu.Unlock() for len(data) > 0 { - space := minPayloadSize(ch.maxRemotePayload, len(data)) + space := min(ch.maxRemotePayload, len(data)) if space, err = ch.remoteWin.reserve(space); err != nil { return n, err } @@ -473,18 +460,6 @@ func (ch *channel) handlePacket(packet []byte) error { } ch.incomingRequests <- &req - case *channelRequestSuccessMsg, *channelRequestFailureMsg: - // Drop responses that arrive when no SendRequest is waiting, to - // prevent a malicious peer from filling ch.msg and stalling the - // mux read loop. The non-blocking send additionally protects the - // loop if a well-behaved caller is slow to read. - if !ch.sentRequestPending.Load() { - return nil - } - select { - case ch.msg <- msg: - default: - } default: ch.msg <- msg } @@ -555,17 +530,7 @@ func (ch *channel) Reject(reason RejectionReason, message string) error { Language: "en", } ch.decided = true - err := ch.sendMessage(reject) - - // Remove the channel from the mux to prevent memory leaks. - // Do not call ch.close() here: no goroutine holds a reference to a - // rejected channel's internal channels (msg, incomingRequests), so - // removing it from chanList is sufficient for GC. Calling close() - // would race with the mux loop goroutine (handlePacket or dropAll), - // causing a panic from closing an already-closed channel. - ch.mux.chanList.remove(ch.localId) - - return err + return ch.sendMessage(reject) } func (ch *channel) Read(data []byte) (int, error) { @@ -621,24 +586,6 @@ func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (boo if wantReply { ch.sentRequestMu.Lock() defer ch.sentRequestMu.Unlock() - - // Open the gate so that responses arriving while this request is in - // flight are allowed to reach ch.msg. Responses arriving while no - // request is pending are dropped by handlePacket. - ch.sentRequestPending.Store(true) - defer ch.sentRequestPending.Store(false) - - // Drain any spurious responses that may have been buffered. This - // prevents a previously buffered unexpected response from being - // consumed instead of the actual response for this request. - drain: - for { - select { - case <-ch.msg: - default: - break drain - } - } } msg := channelRequestMsg{ diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/cipher.go b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/cipher.go index 48d019954..ad2b37057 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/cipher.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/cipher.go @@ -407,7 +407,7 @@ func (c *gcmCipher) readCipherPacket(seqNum uint32, r io.Reader) ([]byte, error) return nil, fmt.Errorf("ssh: illegal padding %d", padding) } - if int(padding)+1 >= len(plain) { + if int(padding+1) >= len(plain) { return nil, fmt.Errorf("ssh: padding %d too large", padding) } plain = plain[1 : length-uint32(padding)] diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/keys.go b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/keys.go index 3482c4d2c..47a07539d 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/keys.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/keys.go @@ -469,12 +469,6 @@ func parseRSA(in []byte) (out PublicKey, rest []byte, err error) { return nil, nil, err } - // 8192 bits is also the maximum RSA key size accepted by crypto/tls for - // signature verification: - // https://github.com/golang/go/blob/69801b25/src/crypto/tls/handshake_client.go#L1096 - if w.N.BitLen() > 8192 { - return nil, nil, errors.New("ssh: rsa modulus too large") - } if w.E.BitLen() > 24 { return nil, nil, errors.New("ssh: exponent too large") } @@ -580,24 +574,6 @@ func checkDSAParams(param *dsa.Parameters) error { return fmt.Errorf("ssh: unsupported DSA key size %d", l) } - // FIPS 186-2 specifies that Q must be exactly 160 bits. We must enforce - // this to prevent DoS attacks where an attacker sends a huge Q which makes - // verification slow. - if l := param.Q.BitLen(); l != 160 { - return fmt.Errorf("ssh: unsupported DSA sub-prime size %d", l) - } - - // The generator G is an element of the group, so it must be strictly less - // than the modulus P. - if param.G.Cmp(param.P) >= 0 { - return errors.New("ssh: DSA generator larger than modulus") - } - - // G must be positive. - if param.G.Sign() <= 0 { - return errors.New("ssh: DSA generator must be positive") - } - return nil } @@ -620,14 +596,6 @@ func parseDSA(in []byte) (out PublicKey, rest []byte, err error) { return nil, nil, err } - // The public value Y must be a non-zero element of the group, i.e. - // strictly between 0 and P. crypto/dsa.Verify does not range-check Y, - // so we reject out-of-range values here to prevent a maliciously - // oversized Y from slowing verification. - if w.Y.Sign() <= 0 || w.Y.Cmp(w.P) >= 0 { - return nil, nil, errors.New("ssh: DSA public value Y out of range") - } - key := &dsaPublicKey{ Parameters: param, Y: w.Y, @@ -901,25 +869,11 @@ type skFields struct { Counter uint32 } -// flagUserPresence is the "user present" bit (UP) in the SK signature -// flags, matching the FIDO CTAP2 authenticatorData UP flag. See -// openssh/PROTOCOL.u2f. -const flagUserPresence = 0x01 - -// errSKMissingUserPresence is returned by SK key Verify methods when -// the signature does not assert user presence and the key was not -// marked as no-touch-required. -var errSKMissingUserPresence = errors.New("ssh: signature missing required user presence flag") - type skECDSAPublicKey struct { // application is a URL-like string, typically "ssh:" for SSH. // see openssh/PROTOCOL.u2f for details. application string ecdsa.PublicKey - // noTouchRequired, when true, disables the default user-presence - // check in Verify. It is set by skKeyWithoutUP on a clone of the - // key, never on an instance shared across authentication attempts. - noTouchRequired bool } func (k *skECDSAPublicKey) Type() string { @@ -1005,10 +959,6 @@ func (k *skECDSAPublicKey) Verify(data []byte, sig *Signature) error { return err } - if skf.Flags&flagUserPresence == 0 && !k.noTouchRequired { - return errSKMissingUserPresence - } - blob := struct { ApplicationDigest []byte `ssh:"rest"` Flags byte @@ -1042,10 +992,6 @@ type skEd25519PublicKey struct { // see openssh/PROTOCOL.u2f for details. application string ed25519.PublicKey - // noTouchRequired, when true, disables the default user-presence - // check in Verify. It is set by skKeyWithoutUP on a clone of the - // key, never on an instance shared across authentication attempts. - noTouchRequired bool } func (k *skEd25519PublicKey) Type() string { @@ -1120,10 +1066,6 @@ func (k *skEd25519PublicKey) Verify(data []byte, sig *Signature) error { return err } - if skf.Flags&flagUserPresence == 0 && !k.noTouchRequired { - return errSKMissingUserPresence - } - blob := struct { ApplicationDigest []byte `ssh:"rest"` Flags byte diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/mux.go b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/mux.go index 3bc4afbd0..d2d24c635 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/mux.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/mux.go @@ -91,10 +91,9 @@ type mux struct { incomingChannels chan NewChannel - globalSentMu sync.Mutex - globalSentPending atomic.Bool - globalResponses chan interface{} - incomingRequests chan *Request + globalSentMu sync.Mutex + globalResponses chan interface{} + incomingRequests chan *Request errCond *sync.Cond err error @@ -142,24 +141,6 @@ func (m *mux) SendRequest(name string, wantReply bool, payload []byte) (bool, [] if wantReply { m.globalSentMu.Lock() defer m.globalSentMu.Unlock() - - // Open the gate so that responses arriving while this request is in - // flight are allowed to reach globalResponses. Any response arriving - // while no request is pending is dropped by handleGlobalPacket. - m.globalSentPending.Store(true) - defer m.globalSentPending.Store(false) - - // Drain any spurious responses that may have been buffered. This prevents - // a previously buffered unexpected response from being consumed instead - // of the actual response for this request. - drain: - for { - select { - case <-m.globalResponses: - default: - break drain - } - } } if err := m.sendMessage(globalRequestMsg{ @@ -286,16 +267,7 @@ func (m *mux) handleGlobalPacket(packet []byte) error { mux: m, } case *globalRequestSuccessMsg, *globalRequestFailureMsg: - // Drop responses that arrive when no SendRequest is waiting, to - // prevent a malicious peer from staging responses for a future - // caller. - if !m.globalSentPending.Load() { - return nil - } - select { - case m.globalResponses <- msg: - default: - } + m.globalResponses <- msg default: panic(fmt.Sprintf("not a global message %#v", msg)) } diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/server.go b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/server.go index 0192a6750..064dcbaf5 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/server.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/crypto/ssh/server.go @@ -34,20 +34,15 @@ type Permissions struct { // or not supported. CriticalOptions map[string]string - // Extensions are extra functionality that the server may offer on - // authenticated connections. Lack of support for an extension does not - // preclude authenticating a user. Common extensions are - // "permit-agent-forwarding", "permit-X11-forwarding". In general the Go - // SSH library does not act on extensions and it is up to server - // implementations to honor them; extensions can also be used to pass data - // from the authentication callbacks to the server application layer. - // - // The one extension acted upon by this library is "no-touch-required", - // which applies only to security-key public keys - // (sk-ecdsa-sha2-nistp256@openssh.com and sk-ssh-ed25519@openssh.com). - // When present, it waives the default requirement that SK signatures - // assert user presence (i.e. a physical touch of the authenticator) - // during signature verification. + // Extensions are extra functionality that the server may + // offer on authenticated connections. Lack of support for an + // extension does not preclude authenticating a user. Common + // extensions are "permit-agent-forwarding", + // "permit-X11-forwarding". The Go SSH library currently does + // not act on any extension, and it is up to server + // implementations to honor them. Extensions can be used to + // pass data from the authentication callbacks to the server + // application layer. Extensions map[string]string // ExtraData allows to store user defined data. @@ -89,79 +84,6 @@ type ServerPreAuthConn interface { SendAuthBanner(string) error } -// noTouchRequiredExtension is the extension name used by OpenSSH in -// authorized_keys options and certificate extensions to mark keys -// whose signatures do not need to assert user presence (touch). See -// ssh-keygen(1) and sshd(8). -const noTouchRequiredExtension = "no-touch-required" - -// noTouchAllowed reports whether the user presence requirement on -// SK signatures should be waived for this authentication attempt. The -// requirement is waived when the "no-touch-required" extension is -// present either in the Permissions returned by the auth callback -// (authorized_keys-level opt-out) or in the certificate's own -// Extensions (CA-level opt-out), matching OpenSSH behavior. OpenSSH -// reads the per-key opt-out only from cert Extensions and -// authorized_keys options (never from CriticalOptions); we follow the -// same rule. -func noTouchAllowed(pubKey PublicKey, perms *Permissions) bool { - if perms != nil { - if _, ok := perms.Extensions[noTouchRequiredExtension]; ok { - return true - } - } - if cert, ok := pubKey.(*Certificate); ok { - if _, ok := cert.Extensions[noTouchRequiredExtension]; ok { - return true - } - } - return false -} - -// skKeyWithoutUP returns a PublicKey equivalent to pubKey but whose -// Verify accepts SK signatures with the user-presence flag clear. If -// pubKey is not (and does not wrap) an SK key, pubKey is returned -// unchanged. The returned value never mutates pubKey: for SK keys a -// shallow copy is made so that the noTouchRequired flag is set only on -// the clone. -// -// The implementation is iterative rather than recursive. When pubKey -// is a *Certificate we unwrap exactly one level to look at the inner -// key. The SSH cert format forbids Certificate.Key from being another -// Certificate (parseCert rejects it), but nothing stops callers from -// constructing such a value directly in Go; a recursive descent could -// otherwise be driven to unbounded depth by a hand-crafted or cyclic -// Certificate. A malformed input of that shape simply returns -// unchanged here. -func skKeyWithoutUP(pubKey PublicKey) PublicKey { - cert, isCert := pubKey.(*Certificate) - target := pubKey - if isCert { - target = cert.Key - } - var cloned PublicKey - switch k := target.(type) { - case *skECDSAPublicKey: - c := *k - c.noTouchRequired = true - cloned = &c - case *skEd25519PublicKey: - c := *k - c.noTouchRequired = true - cloned = &c - default: - // Not an SK key (or a pathological *Certificate wrapping - // another *Certificate): pubKey is already usable for Verify. - return pubKey - } - if !isCert { - return cloned - } - c := *cert - c.Key = cloned - return &c -} - // ServerConfig holds server specific configuration data. type ServerConfig struct { // Config contains configuration shared between client and server. @@ -320,10 +242,8 @@ func (c *pubKeyCache) add(candidate cachedPubKey) { type ServerConn struct { Conn - // If the succeeding authentication callback returned a non-nil Permissions - // pointer, it is stored here. These are the permissions from the final, - // successful authentication method. Permissions returned by callbacks that - // return PartialSuccessError are not preserved and must be nil. + // If the succeeding authentication callback returned a + // non-nil Permissions pointer, it is stored here. Permissions *Permissions } @@ -817,15 +737,8 @@ userAuthLoop: } signedData := buildDataSignedForAuth(sessionID, userAuthReq, algo, pubKeyData) - // pubKey is reused below for VerifiedPublicKeyCallback and - // must remain the key as presented by the client; derive a - // separate value for Verify that carries any applicable - // no-touch-required opt-out. - pubKeyForVerify := pubKey - if noTouchAllowed(pubKey, candidate.perms) { - pubKeyForVerify = skKeyWithoutUP(pubKey) - } - if err := pubKeyForVerify.Verify(signedData, sig); err != nil { + + if err := pubKey.Verify(signedData, sig); err != nil { return nil, err } @@ -837,13 +750,6 @@ userAuthLoop: // considered verified and the callback must not run. perms, authErr = config.VerifiedPublicKeyCallback(s, pubKey, perms, algo) } - if authErr == nil && perms != nil && perms.CriticalOptions != nil { - if saco := perms.CriticalOptions[sourceAddressCriticalOption]; saco != "" { - if err := checkSourceAddress(s.RemoteAddr(), saco); err != nil { - authErr = err - } - } - } } case "gssapi-with-mic": if authConfig.GSSAPIWithMICConfig == nil { @@ -918,13 +824,6 @@ userAuthLoop: var failureMsg userAuthFailureMsg if partialSuccess, ok := authErr.(*PartialSuccessError); ok { - // Permissions are not preserved between authentication steps. To - // avoid confusion about the final state of the connection, we - // disallow returning non-nil Permissions combined with - // PartialSuccessError. - if perms != nil { - return nil, errors.New("ssh: permissions must be nil when returning PartialSuccessError") - } // After a partial success error we don't allow changing the user // name and execute the NoClientAuthCallback. partialSuccessReturned = true diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/parse.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/parse.go index b3d2a2558..88fc0056a 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/parse.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/parse.go @@ -5,11 +5,9 @@ package html import ( - "cmp" "errors" "fmt" "io" - "slices" "strings" a "golang.org/x/net/html/atom" @@ -330,14 +328,6 @@ func (p *parser) addText(text string) { }) } -func attrCompare(a, b Attribute) int { - return cmp.Or( - cmp.Compare(a.Namespace, b.Namespace), - cmp.Compare(a.Key, b.Key), - cmp.Compare(a.Val, b.Val), - ) -} - // addElement adds a child element based on the current token. func (p *parser) addElement() { p.addChild(&Node{ @@ -353,10 +343,6 @@ func (p *parser) addFormattingElement() { tagAtom, attr := p.tok.DataAtom, p.tok.Attr p.addElement() - // In order to optimize the search, we need the attributes to be sorted, so we - // can just use slices.Equal. - slices.SortFunc(attr, attrCompare) - // Implement the Noah's Ark clause, but with three per family instead of two. identicalElements := 0 findIdenticalElements: @@ -374,7 +360,19 @@ findIdenticalElements: if n.DataAtom != tagAtom { continue } - if !slices.Equal(n.Attr, attr) { + if len(n.Attr) != len(attr) { + continue + } + compareAttributes: + for _, t0 := range n.Attr { + for _, t1 := range attr { + if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val { + // Found a match for this attribute, continue with the next attribute. + continue compareAttributes + } + } + // If we get here, there is no attribute that matches a. + // Therefore the element is not identical to the new one. continue findIdenticalElements } @@ -384,11 +382,7 @@ findIdenticalElements: } } - // Sort the attributes to optimize future identical-element searches. - top := p.top() - slices.SortFunc(top.Attr, attrCompare) - - p.afe = append(p.afe, top) + p.afe = append(p.afe, p.top()) } // Section 12.2.4.3. @@ -1378,6 +1372,8 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) { } // inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM. +// "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content +// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign func (p *parser) inBodyEndTagOther(tagAtom a.Atom, tagName string) { for i := len(p.oe) - 1; i >= 0; i-- { // Two element nodes have the same tag if they have the same Data (a @@ -1387,7 +1383,7 @@ func (p *parser) inBodyEndTagOther(tagAtom a.Atom, tagName string) { // Uncommon (custom) tags get a zero DataAtom. // // The if condition here is equivalent to (p.oe[i].Data == tagName). - if p.oe[i].Namespace == "" && (p.oe[i].DataAtom == tagAtom) && + if (p.oe[i].DataAtom == tagAtom) && ((tagAtom != 0) || (p.oe[i].Data == tagName)) { p.oe = p.oe[:i] break diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/render.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/render.go index 767eeae25..0157d89e1 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/render.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/render.go @@ -113,14 +113,14 @@ func render1(w writer, n *Node) error { if _, err := w.WriteString(" PUBLIC "); err != nil { return err } - if err := writeDoctypeQuoted(w, p); err != nil { + if err := writeQuoted(w, p); err != nil { return err } if s != "" { if err := w.WriteByte(' '); err != nil { return err } - if err := writeDoctypeQuoted(w, s); err != nil { + if err := writeQuoted(w, s); err != nil { return err } } @@ -128,7 +128,7 @@ func render1(w writer, n *Node) error { if _, err := w.WriteString(" SYSTEM "); err != nil { return err } - if err := writeDoctypeQuoted(w, s); err != nil { + if err := writeQuoted(w, s); err != nil { return err } } @@ -243,50 +243,27 @@ func childTextNodesAreLiteral(n *Node) bool { if n.Namespace != "" { return false } - switch n.Data { case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp": - // We need to check if n is a node that was fostered from a HTML namespace - // into a non-HTML namespace (in which case, different rules apply to it). - // We do this by walking up the tree until we find a node with a non-empty - // namespace. If we find such a node, we also have to check if it's - // an HTML integration point. If it isn't, then the node we're currently - // looking at is foster-parented and we should return false. - for p := n.Parent; p != nil; p = p.Parent { - if p.Namespace != "" { - if !htmlIntegrationPoint(p) { - return false - } - break - } - } - return true default: return false } } -// writeDoctypeQuoted writes s to w surrounded by quotes. Normally it will use double +// writeQuoted writes s to w surrounded by quotes. Normally it will use double // quotes, but if s contains a double quote, it will use single quotes. -// If s contains any '>' characters, they are replaced with > in order -// to prevent triggering an abrupt-doctype-system-identifier parse error. // It is used for writing the identifiers in a doctype declaration. // In valid HTML, they can't contain both types of quotes. -func writeDoctypeQuoted(w writer, s string) error { +func writeQuoted(w writer, s string) error { var q byte = '"' if strings.Contains(s, `"`) { - // parseDoctype will never produce a Node with both quote types, but a user - // can construct their own Node that violates this assumption. - if strings.Contains(s, `'`) { - return errors.New("doctype contains both quote types, cannot be safely rendered") - } q = '\'' } if err := w.WriteByte(q); err != nil { return err } - if _, err := w.WriteString(strings.ReplaceAll(s, ">", ">")); err != nil { + if _, err := w.WriteString(s); err != nil { return err } if err := w.WriteByte(q); err != nil { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/token.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/token.go index 058dfb216..6598c1f7b 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/token.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/html/token.go @@ -156,7 +156,6 @@ type Tokenizer struct { // incremented on each call to TagAttr. pendingAttr [2]span attr [][2]span - attrNames map[string]bool nAttrReturned int // rawTag is the "script" in "" that closes the next token. If // non-empty, the subsequent call to Next will return a raw or RCDATA text @@ -868,7 +867,6 @@ func (z *Tokenizer) readStartTag() TokenType { func (z *Tokenizer) readTag(saveAttr bool) { z.attr = z.attr[:0] z.nAttrReturned = 0 - clear(z.attrNames) // Read the tag name and attribute key/value pairs. z.readTagName() if z.skipWhiteSpace(); z.err != nil { @@ -882,11 +880,9 @@ func (z *Tokenizer) readTag(saveAttr bool) { z.raw.end-- z.readTagAttrKey() z.readTagAttrVal() - // Save pendingAttr if saveAttr and that attribute has a non-empty key, and the key hasn't been seen before. - key := strings.ToLower(string(z.buf[z.pendingAttr[0].start:z.pendingAttr[0].end])) - if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end && !z.attrNames[key] { + // Save pendingAttr if saveAttr and that attribute has a non-empty key. + if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end { z.attr = append(z.attr, z.pendingAttr) - z.attrNames[key] = true } if z.skipWhiteSpace(); z.err != nil { break @@ -1277,9 +1273,8 @@ func NewTokenizer(r io.Reader) *Tokenizer { // The input is assumed to be UTF-8 encoded. func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer { z := &Tokenizer{ - r: r, - buf: make([]byte, 0, 4096), - attrNames: make(map[string]bool), + r: r, + buf: make([]byte, 0, 4096), } if contextTag != "" { switch s := strings.ToLower(contextTag); s { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server.go index a7d2053b6..fbb145115 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server.go @@ -2657,6 +2657,21 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) { return len(p), nil } +// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys +// that, if present, signals that the map entry is actually for +// the response trailers, and not the response headers. The prefix +// is stripped after the ServeHTTP call finishes and the values are +// sent in the trailers. +// +// This mechanism is intended only for trailers that are not known +// prior to the headers being written. If the set of trailers is fixed +// or known before the header is written, the normal Go trailers mechanism +// is preferred: +// +// https://golang.org/pkg/net/http/#ResponseWriter +// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers +const TrailerPrefix = "Trailer:" + // promoteUndeclaredTrailers permits http.Handlers to set trailers // after the header has already been flushed. Because the Go // ResponseWriter interface has no way to set Trailers (only the @@ -2933,6 +2948,12 @@ func (w *responseWriter) handlerDone() { responseWriterStatePool.Put(rws) } +// Push errors. +var ( + ErrRecursivePush = errors.New("http2: recursive push not allowed") + ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS") +) + var _ http.Pusher = (*responseWriter)(nil) func (w *responseWriter) Push(target string, opts *http.PushOptions) error { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server_common.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server_common.go index 449538c86..e2faeb9b6 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server_common.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server_common.go @@ -6,33 +6,11 @@ package http2 import ( "context" - "errors" "net" "net/http" "time" ) -// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys -// that, if present, signals that the map entry is actually for -// the response trailers, and not the response headers. The prefix -// is stripped after the ServeHTTP call finishes and the values are -// sent in the trailers. -// -// This mechanism is intended only for trailers that are not known -// prior to the headers being written. If the set of trailers is fixed -// or known before the header is written, the normal Go trailers mechanism -// is preferred: -// -// https://golang.org/pkg/net/http/#ResponseWriter -// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers -const TrailerPrefix = "Trailer:" - -// Push errors. -var ( - ErrRecursivePush = errors.New("http2: recursive push not allowed") - ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS") -) - // ConfigureServer adds HTTP/2 support to a net/http Server. // // The configuration conf may be nil. diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server_wrap.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server_wrap.go index a7a09551c..9e6003b89 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server_wrap.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/server_wrap.go @@ -159,43 +159,3 @@ type FrameWriteRequest struct { // to avoid duplicating an exported symbol across two files, // but the changes required to make this work are fairly large. } - -func (wr FrameWriteRequest) StreamID() uint32 { - return 0 -} - -func (wr FrameWriteRequest) DataSize() int { - return 0 -} - -func (wr FrameWriteRequest) Consume(n int32) (FrameWriteRequest, FrameWriteRequest, int) { - return FrameWriteRequest{}, FrameWriteRequest{}, 0 -} - -func (wr FrameWriteRequest) String() string { - return "" -} - -// NewPriorityWriteScheduler is deprecated. -// -// Deprecated: User-provided write schedulers are deprecated. -func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler { - return unsupportedWriteScheduler{} -} - -// NewRandomWriteScheduler is deprecated. -// -// Deprecated: User-provided write schedulers are deprecated. -func NewRandomWriteScheduler() WriteScheduler { - return unsupportedWriteScheduler{} -} - -type unsupportedWriteScheduler struct{} - -func (unsupportedWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {} -func (unsupportedWriteScheduler) CloseStream(streamID uint32) {} -func (unsupportedWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {} -func (unsupportedWriteScheduler) Push(wr FrameWriteRequest) {} -func (unsupportedWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) { - return FrameWriteRequest{}, false -} diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/transport.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/transport.go index 08ac409b0..882a92694 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/transport.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/transport.go @@ -399,6 +399,27 @@ func (sew stickyErrWriter) Write(p []byte) (n int, err error) { return n, err } +// noCachedConnError is the concrete type of ErrNoCachedConn, which +// needs to be detected by net/http regardless of whether it's its +// bundled version (in h2_bundle.go with a rewritten type name) or +// from a user's x/net/http2. As such, as it has a unique method name +// (IsHTTP2NoCachedConnError) that net/http sniffs for via func +// isNoCachedConnError. +type noCachedConnError struct{} + +func (noCachedConnError) IsHTTP2NoCachedConnError() {} +func (noCachedConnError) Error() string { return "http2: no cached connection was available" } + +// isNoCachedConnError reports whether err is of type noCachedConnError +// or its equivalent renamed type in net/http2's h2_bundle.go. Both types +// may coexist in the same running program. +func isNoCachedConnError(err error) bool { + _, ok := err.(interface{ IsHTTP2NoCachedConnError() }) + return ok +} + +var ErrNoCachedConn error = noCachedConnError{} + func (t *Transport) roundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) { switch req.URL.Scheme { case "https": @@ -1765,6 +1786,19 @@ func (cc *ClientConn) readLoop() { } } +// GoAwayError is returned by the Transport when the server closes the +// TCP connection after sending a GOAWAY frame. +type GoAwayError struct { + LastStreamID uint32 + ErrCode ErrCode + DebugData string +} + +func (e GoAwayError) Error() string { + return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q", + e.LastStreamID, e.ErrCode, e.DebugData) +} + func isEOFOrNetReadError(err error) bool { if err == io.EOF { return true diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/transport_common.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/transport_common.go index b9f52932e..f7f85b3ad 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/transport_common.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/transport_common.go @@ -411,37 +411,3 @@ func (t *Transport) dialTLSWithContext(ctx context.Context, network, addr string tlsCn := cn.(*tls.Conn) // DialContext comment promises this will always succeed return tlsCn, nil } - -// GoAwayError is returned by the Transport when the server closes the -// TCP connection after sending a GOAWAY frame. -type GoAwayError struct { - LastStreamID uint32 - ErrCode ErrCode - DebugData string -} - -func (e GoAwayError) Error() string { - return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q", - e.LastStreamID, e.ErrCode, e.DebugData) -} - -// noCachedConnError is the concrete type of ErrNoCachedConn, which -// needs to be detected by net/http regardless of whether it's its -// bundled version (in h2_bundle.go with a rewritten type name) or -// from a user's x/net/http2. As such, as it has a unique method name -// (IsHTTP2NoCachedConnError) that net/http sniffs for via func -// isNoCachedConnError. -type noCachedConnError struct{} - -func (noCachedConnError) IsHTTP2NoCachedConnError() {} -func (noCachedConnError) Error() string { return "http2: no cached connection was available" } - -// isNoCachedConnError reports whether err is of type noCachedConnError -// or its equivalent renamed type in net/http2's h2_bundle.go. Both types -// may coexist in the same running program. -func isNoCachedConnError(err error) bool { - _, ok := err.(interface{ IsHTTP2NoCachedConnError() }) - return ok -} - -var ErrNoCachedConn error = noCachedConnError{} diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/writesched_common.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/writesched_common.go index 75354c1ff..957bc659e 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/writesched_common.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/writesched_common.go @@ -47,44 +47,3 @@ type OpenStreamOptions struct { // priority is used to set the priority of the newly opened stream. priority PriorityParam } - -// PriorityWriteSchedulerConfig configures a priorityWriteScheduler. -// -// Deprecated: User-provided write schedulers are deprecated. -type PriorityWriteSchedulerConfig struct { - // MaxClosedNodesInTree controls the maximum number of closed streams to - // retain in the priority tree. Setting this to zero saves a small amount - // of memory at the cost of performance. - // - // See RFC 7540, Section 5.3.4: - // "It is possible for a stream to become closed while prioritization - // information ... is in transit. ... This potentially creates suboptimal - // prioritization, since the stream could be given a priority that is - // different from what is intended. To avoid these problems, an endpoint - // SHOULD retain stream prioritization state for a period after streams - // become closed. The longer state is retained, the lower the chance that - // streams are assigned incorrect or default priority values." - MaxClosedNodesInTree int - - // MaxIdleNodesInTree controls the maximum number of idle streams to - // retain in the priority tree. Setting this to zero saves a small amount - // of memory at the cost of performance. - // - // See RFC 7540, Section 5.3.4: - // Similarly, streams that are in the "idle" state can be assigned - // priority or become a parent of other streams. This allows for the - // creation of a grouping node in the dependency tree, which enables - // more flexible expressions of priority. Idle streams begin with a - // default priority (Section 5.3.5). - MaxIdleNodesInTree int - - // ThrottleOutOfOrderWrites enables write throttling to help ensure that - // data is delivered in priority order. This works around a race where - // stream B depends on stream A and both streams are about to call Write - // to queue DATA frames. If B wins the race, a naive scheduler would eagerly - // write as much data from B as possible, but this is suboptimal because A - // is a higher-priority stream. With throttling enabled, we write a small - // amount of data from B to minimize the amount of bandwidth that B can - // steal from A. - ThrottleOutOfOrderWrites bool -} diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go index 10e67f7ce..ccd1afef2 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/net/http2/writesched_priority_rfc7540.go @@ -15,6 +15,47 @@ import ( // RFC 7540, Section 5.3.5: the default weight is 16. const priorityDefaultWeightRFC7540 = 15 // 16 = 15 + 1 +// PriorityWriteSchedulerConfig configures a priorityWriteScheduler. +// +// Deprecated: User-provided write schedulers are deprecated. +type PriorityWriteSchedulerConfig struct { + // MaxClosedNodesInTree controls the maximum number of closed streams to + // retain in the priority tree. Setting this to zero saves a small amount + // of memory at the cost of performance. + // + // See RFC 7540, Section 5.3.4: + // "It is possible for a stream to become closed while prioritization + // information ... is in transit. ... This potentially creates suboptimal + // prioritization, since the stream could be given a priority that is + // different from what is intended. To avoid these problems, an endpoint + // SHOULD retain stream prioritization state for a period after streams + // become closed. The longer state is retained, the lower the chance that + // streams are assigned incorrect or default priority values." + MaxClosedNodesInTree int + + // MaxIdleNodesInTree controls the maximum number of idle streams to + // retain in the priority tree. Setting this to zero saves a small amount + // of memory at the cost of performance. + // + // See RFC 7540, Section 5.3.4: + // Similarly, streams that are in the "idle" state can be assigned + // priority or become a parent of other streams. This allows for the + // creation of a grouping node in the dependency tree, which enables + // more flexible expressions of priority. Idle streams begin with a + // default priority (Section 5.3.5). + MaxIdleNodesInTree int + + // ThrottleOutOfOrderWrites enables write throttling to help ensure that + // data is delivered in priority order. This works around a race where + // stream B depends on stream A and both streams are about to call Write + // to queue DATA frames. If B wins the race, a naive scheduler would eagerly + // write as much data from B as possible, but this is suboptimal because A + // is a higher-priority stream. With throttling enabled, we write a small + // amount of data from B to minimize the amount of bandwidth that B can + // steal from A. + ThrottleOutOfOrderWrites bool +} + // NewPriorityWriteScheduler constructs a WriteScheduler that schedules // frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3. // If cfg is nil, default options are used. diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu.go index f1ce515d5..63541994e 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu.go @@ -152,17 +152,13 @@ var ARM struct { // The booleans in Loong64 contain the correspondingly named cpu feature bit. // The struct is padded to avoid false sharing. var Loong64 struct { - _ CacheLinePad - HasLSX bool // support 128-bit vector extension - HasLASX bool // support 256-bit vector extension - HasCRC32 bool // support CRC instruction - HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} - HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction - HasLLACQ_SCREL bool // support LLACQ.{W/D}, SCREL.{W/D} instruction - HasSCQ bool // support SC.Q instruction - HasDBAR_HINTS bool // supports finer-grained DBAR hints - - _ CacheLinePad + _ CacheLinePad + HasLSX bool // support 128-bit vector extension + HasLASX bool // support 256-bit vector extension + HasCRC32 bool // support CRC instruction + HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction + HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} instruction + _ CacheLinePad } // MIPS64X contains the supported CPU features of the current mips64/mips64le @@ -236,7 +232,6 @@ var RISCV64 struct { HasZba bool // Address generation instructions extension HasZbb bool // Basic bit-manipulation extension HasZbs bool // Single-bit instructions extension - HasZbc bool // Carryless multiplication extension HasZvbb bool // Vector Basic Bit-manipulation HasZvbc bool // Vector Carryless Multiplication HasZvkb bool // Vector Cryptography Bit-manipulation diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go index f4fb52ee9..ad741536f 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go @@ -58,7 +58,6 @@ const ( riscv_HWPROBE_EXT_ZBA = 0x8 riscv_HWPROBE_EXT_ZBB = 0x10 riscv_HWPROBE_EXT_ZBS = 0x20 - riscv_HWPROBE_EXT_ZBC = 0x80 riscv_HWPROBE_EXT_ZVBB = 0x20000 riscv_HWPROBE_EXT_ZVBC = 0x40000 riscv_HWPROBE_EXT_ZVKB = 0x80000 @@ -109,7 +108,6 @@ func doinit() { RISCV64.HasZba = isSet(v, riscv_HWPROBE_EXT_ZBA) RISCV64.HasZbb = isSet(v, riscv_HWPROBE_EXT_ZBB) RISCV64.HasZbs = isSet(v, riscv_HWPROBE_EXT_ZBS) - RISCV64.HasZbc = isSet(v, riscv_HWPROBE_EXT_ZBC) RISCV64.HasZvbb = isSet(v, riscv_HWPROBE_EXT_ZVBB) RISCV64.HasZvbc = isSet(v, riscv_HWPROBE_EXT_ZVBC) RISCV64.HasZvkb = isSet(v, riscv_HWPROBE_EXT_ZVKB) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_loong64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_loong64.go index 8c234b441..45ecb29ae 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_loong64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_loong64.go @@ -15,13 +15,8 @@ const ( cpucfg1_CRC32 = 1 << 25 // CPUCFG2 bits - cpucfg2_LAM_BH = 1 << 27 - cpucfg2_LAMCAS = 1 << 28 - cpucfg2_LLACQ_SCREL = 1 << 29 - cpucfg2_SCQ = 1 << 30 - - // CPUCFG3 bits - cpucfg3_DBAR_HINTS = 1 << 17 + cpucfg2_LAM_BH = 1 << 27 + cpucfg2_LAMCAS = 1 << 28 ) func initOptions() { @@ -31,9 +26,6 @@ func initOptions() { {Name: "crc32", Feature: &Loong64.HasCRC32}, {Name: "lam_bh", Feature: &Loong64.HasLAM_BH}, {Name: "lamcas", Feature: &Loong64.HasLAMCAS}, - {Name: "llacq_screl", Feature: &Loong64.HasLLACQ_SCREL}, - {Name: "scq", Feature: &Loong64.HasSCQ}, - {Name: "dbar_hints", Feature: &Loong64.HasDBAR_HINTS}, } // The CPUCFG data on Loong64 only reflects the hardware capabilities, @@ -45,14 +37,10 @@ func initOptions() { // through CPUCFG cfg1 := get_cpucfg(1) cfg2 := get_cpucfg(2) - cfg3 := get_cpucfg(3) Loong64.HasCRC32 = cfgIsSet(cfg1, cpucfg1_CRC32) Loong64.HasLAMCAS = cfgIsSet(cfg2, cpucfg2_LAMCAS) Loong64.HasLAM_BH = cfgIsSet(cfg2, cpucfg2_LAM_BH) - Loong64.HasLLACQ_SCREL = cfgIsSet(cfg2, cpucfg2_LLACQ_SCREL) - Loong64.HasSCQ = cfgIsSet(cfg2, cpucfg2_SCQ) - Loong64.HasDBAR_HINTS = cfgIsSet(cfg3, cpucfg3_DBAR_HINTS) } func get_cpucfg(reg uint32) uint32 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_riscv64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_riscv64.go index d4e9885f3..0f617aef5 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_riscv64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/cpu/cpu_riscv64.go @@ -16,7 +16,6 @@ func initOptions() { {Name: "zba", Feature: &RISCV64.HasZba}, {Name: "zbb", Feature: &RISCV64.HasZbb}, {Name: "zbs", Feature: &RISCV64.HasZbs}, - {Name: "zbc", Feature: &RISCV64.HasZbc}, // RISC-V Cryptography Extensions {Name: "zvbb", Feature: &RISCV64.HasZvbb}, {Name: "zvbc", Feature: &RISCV64.HasZvbc}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/mkerrors.sh b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/mkerrors.sh index fa74cfe9e..fd39be4ef 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -354,9 +354,6 @@ struct ltchars { // Renamed in v6.16, commit c6d732c38f93 ("net: ethtool: remove duplicate defines for family info") #define ETHTOOL_FAMILY_NAME ETHTOOL_GENL_NAME #define ETHTOOL_FAMILY_VERSION ETHTOOL_GENL_VERSION - -// Removed in v6.17, commit 760e6f7befba ("futex: Remove support for IMMUTABLE") -#define PR_FUTEX_HASH_GET_IMMUTABLE 3 ' includes_NetBSD=' diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/readv_unix.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/readv_unix.go deleted file mode 100644 index 38a2be937..000000000 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/readv_unix.go +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2026 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin || linux || openbsd - -package unix - -import "unsafe" - -// minIovec is the size of the small initial allocation used by -// Readv, Writev, etc. -// -// This small allocation gets stack allocated, which lets the -// common use case of len(iovs) <= minIovec avoid more expensive -// heap allocations. -const minIovec = 8 - -// appendBytes converts bs to Iovecs and appends them to vecs. -func appendBytes(vecs []Iovec, bs [][]byte) []Iovec { - for _, b := range bs { - var v Iovec - v.SetLen(len(b)) - if len(b) > 0 { - v.Base = &b[0] - } else { - v.Base = (*byte)(unsafe.Pointer(&_zero)) - } - vecs = append(vecs, v) - } - return vecs -} - -// writevRaceDetect tells the race detector that the program -// has read the first n bytes stored in iovecs. -func writevRaceDetect(iovecs []Iovec, n int) { - if !raceenabled { - return - } - for i := 0; n > 0 && i < len(iovecs); i++ { - m := min(int(iovecs[i].Len), n) - n -= m - if m > 0 { - raceReadRange(unsafe.Pointer(iovecs[i].Base), m) - } - } -} - -// readvRaceDetect tells the race detector that the program -// has written to the first n bytes stored in iovecs. -func readvRaceDetect(iovecs []Iovec, n int, err error) { - if !raceenabled { - return - } - for i := 0; n > 0 && i < len(iovecs); i++ { - m := min(int(iovecs[i].Len), n) - n -= m - if m > 0 { - raceWriteRange(unsafe.Pointer(iovecs[i].Base), m) - } - } - if err == nil { - raceAcquire(unsafe.Pointer(&ioSync)) - } -} - -func Readv(fd int, iovs [][]byte) (n int, err error) { - iovecs := make([]Iovec, 0, minIovec) - iovecs = appendBytes(iovecs, iovs) - n, err = readv(fd, iovecs) - readvRaceDetect(iovecs, n, err) - return n, err -} - -func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { - iovecs := make([]Iovec, 0, minIovec) - iovecs = appendBytes(iovecs, iovs) - n, err = preadv(fd, iovecs, offset) - readvRaceDetect(iovecs, n, err) - return n, err -} - -func Writev(fd int, iovs [][]byte) (n int, err error) { - iovecs := make([]Iovec, 0, minIovec) - iovecs = appendBytes(iovecs, iovs) - if raceenabled { - raceReleaseMerge(unsafe.Pointer(&ioSync)) - } - n, err = writev(fd, iovecs) - writevRaceDetect(iovecs, n) - return n, err -} - -func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { - iovecs := make([]Iovec, 0, minIovec) - iovecs = appendBytes(iovecs, iovs) - if raceenabled { - raceReleaseMerge(unsafe.Pointer(&ioSync)) - } - n, err = pwritev(fd, iovecs, offset) - writevRaceDetect(iovecs, n) - return n, err -} diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_darwin.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_darwin.go index 38590ca81..7838ca5db 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -602,6 +602,95 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI return } +const minIovec = 8 + +func Readv(fd int, iovs [][]byte) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + n, err = readv(fd, iovecs) + readvRacedetect(iovecs, n, err) + return n, err +} + +func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + n, err = preadv(fd, iovecs, offset) + readvRacedetect(iovecs, n, err) + return n, err +} + +func Writev(fd int, iovs [][]byte) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + n, err = writev(fd, iovecs) + writevRacedetect(iovecs, n) + return n, err +} + +func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + n, err = pwritev(fd, iovecs, offset) + writevRacedetect(iovecs, n) + return n, err +} + +func appendBytes(vecs []Iovec, bs [][]byte) []Iovec { + for _, b := range bs { + var v Iovec + v.SetLen(len(b)) + if len(b) > 0 { + v.Base = &b[0] + } else { + v.Base = (*byte)(unsafe.Pointer(&_zero)) + } + vecs = append(vecs, v) + } + return vecs +} + +func writevRacedetect(iovecs []Iovec, n int) { + if !raceenabled { + return + } + for i := 0; n > 0 && i < len(iovecs); i++ { + m := int(iovecs[i].Len) + if m > n { + m = n + } + n -= m + if m > 0 { + raceReadRange(unsafe.Pointer(iovecs[i].Base), m) + } + } +} + +func readvRacedetect(iovecs []Iovec, n int, err error) { + if !raceenabled { + return + } + for i := 0; n > 0 && i < len(iovecs); i++ { + m := int(iovecs[i].Len) + if m > n { + m = n + } + n -= m + if m > 0 { + raceWriteRange(unsafe.Pointer(iovecs[i].Base), m) + } + } + if err == nil { + raceAcquire(unsafe.Pointer(&ioSync)) + } +} + //sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_linux.go index ce4d7ab1e..f7b82bcca 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -2150,10 +2150,33 @@ func Signalfd(fd int, sigmask *Sigset_t, flags int) (newfd int, err error) { //sys exitThread(code int) (err error) = SYS_EXIT //sys readv(fd int, iovs []Iovec) (n int, err error) = SYS_READV //sys writev(fd int, iovs []Iovec) (n int, err error) = SYS_WRITEV -//sys preadvSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PREADV -//sys pwritevSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PWRITEV -//sys preadv2Syscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PREADV2 -//sys pwritev2Syscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PWRITEV2 +//sys preadv(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PREADV +//sys pwritev(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) = SYS_PWRITEV +//sys preadv2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PREADV2 +//sys pwritev2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) = SYS_PWRITEV2 + +// minIovec is the size of the small initial allocation used by +// Readv, Writev, etc. +// +// This small allocation gets stack allocated, which lets the +// common use case of len(iovs) <= minIovs avoid more expensive +// heap allocations. +const minIovec = 8 + +// appendBytes converts bs to Iovecs and appends them to vecs. +func appendBytes(vecs []Iovec, bs [][]byte) []Iovec { + for _, b := range bs { + var v Iovec + v.SetLen(len(b)) + if len(b) > 0 { + v.Base = &b[0] + } else { + v.Base = (*byte)(unsafe.Pointer(&_zero)) + } + vecs = append(vecs, v) + } + return vecs +} // offs2lohi splits offs into its low and high order bits. func offs2lohi(offs int64) (lo, hi uintptr) { @@ -2161,23 +2184,69 @@ func offs2lohi(offs int64) (lo, hi uintptr) { return uintptr(offs), uintptr(uint64(offs) >> (longBits - 1) >> 1) // two shifts to avoid false positive in vet } -func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { +func Readv(fd int, iovs [][]byte) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + n, err = readv(fd, iovecs) + readvRacedetect(iovecs, n, err) + return n, err +} + +func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) lo, hi := offs2lohi(offset) - return preadvSyscall(fd, iovecs, lo, hi) + n, err = preadv(fd, iovecs, lo, hi) + readvRacedetect(iovecs, n, err) + return n, err } func Preadv2(fd int, iovs [][]byte, offset int64, flags int) (n int, err error) { iovecs := make([]Iovec, 0, minIovec) iovecs = appendBytes(iovecs, iovs) lo, hi := offs2lohi(offset) - n, err = preadv2Syscall(fd, iovecs, lo, hi, flags) - readvRaceDetect(iovecs, n, err) + n, err = preadv2(fd, iovecs, lo, hi, flags) + readvRacedetect(iovecs, n, err) + return n, err +} + +func readvRacedetect(iovecs []Iovec, n int, err error) { + if !raceenabled { + return + } + for i := 0; n > 0 && i < len(iovecs); i++ { + m := min(int(iovecs[i].Len), n) + n -= m + if m > 0 { + raceWriteRange(unsafe.Pointer(iovecs[i].Base), m) + } + } + if err == nil { + raceAcquire(unsafe.Pointer(&ioSync)) + } +} + +func Writev(fd int, iovs [][]byte) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + n, err = writev(fd, iovecs) + writevRacedetect(iovecs, n) return n, err } -func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { +func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } lo, hi := offs2lohi(offset) - return pwritevSyscall(fd, iovecs, lo, hi) + n, err = pwritev(fd, iovecs, lo, hi) + writevRacedetect(iovecs, n) + return n, err } func Pwritev2(fd int, iovs [][]byte, offset int64, flags int) (n int, err error) { @@ -2187,11 +2256,24 @@ func Pwritev2(fd int, iovs [][]byte, offset int64, flags int) (n int, err error) raceReleaseMerge(unsafe.Pointer(&ioSync)) } lo, hi := offs2lohi(offset) - n, err = pwritev2Syscall(fd, iovecs, lo, hi, flags) - writevRaceDetect(iovecs, n) + n, err = pwritev2(fd, iovecs, lo, hi, flags) + writevRacedetect(iovecs, n) return n, err } +func writevRacedetect(iovecs []Iovec, n int) { + if !raceenabled { + return + } + for i := 0; n > 0 && i < len(iovecs); i++ { + m := min(int(iovecs[i].Len), n) + n -= m + if m > 0 { + raceReadRange(unsafe.Pointer(iovecs[i].Base), m) + } + } +} + // mmap varies by architecture; see syscall_linux_*.go. //sys munmap(addr uintptr, length uintptr) (err error) //sys mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 7b0ef8e12..b86ded549 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -300,10 +300,6 @@ func Uname(uname *Utsname) error { //sys Pathconf(path string, name int) (val int, err error) //sys pread(fd int, p []byte, offset int64) (n int, err error) //sys pwrite(fd int, p []byte, offset int64) (n int, err error) -//sys readv(fd int, iovecs []Iovec) (n int, err error) -//sys writev(fd int, iovecs []Iovec) (n int, err error) -//sys preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) -//sys pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) //sys read(fd int, p []byte) (n int, err error) //sys Readlink(path string, buf []byte) (n int, err error) //sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux.go index 9d72a6b73..120a7b35d 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -353,10 +353,8 @@ const ( AUDIT_MAC_IPSEC_EVENT = 0x587 AUDIT_MAC_MAP_ADD = 0x581 AUDIT_MAC_MAP_DEL = 0x582 - AUDIT_MAC_OBJ_CONTEXTS = 0x592 AUDIT_MAC_POLICY_LOAD = 0x57b AUDIT_MAC_STATUS = 0x57c - AUDIT_MAC_TASK_CONTEXTS = 0x591 AUDIT_MAC_UNLBL_ALLOW = 0x57e AUDIT_MAC_UNLBL_STCADD = 0x588 AUDIT_MAC_UNLBL_STCDEL = 0x589 @@ -593,13 +591,8 @@ const ( CAN_CTRLMODE_LOOPBACK = 0x1 CAN_CTRLMODE_ONE_SHOT = 0x8 CAN_CTRLMODE_PRESUME_ACK = 0x40 - CAN_CTRLMODE_RESTRICTED = 0x800 CAN_CTRLMODE_TDC_AUTO = 0x200 CAN_CTRLMODE_TDC_MANUAL = 0x400 - CAN_CTRLMODE_XL = 0x1000 - CAN_CTRLMODE_XL_TDC_AUTO = 0x2000 - CAN_CTRLMODE_XL_TDC_MANUAL = 0x4000 - CAN_CTRLMODE_XL_TMS = 0x8000 CAN_EFF_FLAG = 0x80000000 CAN_EFF_ID_BITS = 0x1d CAN_EFF_MASK = 0x1fffffff @@ -807,8 +800,6 @@ const ( DEVLINK_PORT_FN_CAP_IPSEC_PACKET = 0x8 DEVLINK_PORT_FN_CAP_MIGRATABLE = 0x2 DEVLINK_PORT_FN_CAP_ROCE = 0x1 - DEVLINK_RATE_TCS_MAX = 0x8 - DEVLINK_RATE_TC_INDEX_MAX = 0x7 DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX = 0x14 DEVLINK_SUPPORTED_FLASH_OVERWRITE_SECTIONS = 0x3 DEVMEM_MAGIC = 0x454d444d @@ -1195,7 +1186,6 @@ const ( ETH_P_MPLS_UC = 0x8847 ETH_P_MRP = 0x88e3 ETH_P_MVRP = 0x88f5 - ETH_P_MXLGSW = 0x88c3 ETH_P_NCSI = 0x88f8 ETH_P_NSH = 0x894f ETH_P_PAE = 0x888e @@ -1228,7 +1218,6 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 - ETH_P_YT921X = 0x9988 ET_CORE = 0x4 ET_DYN = 0x3 ET_EXEC = 0x2 @@ -1269,7 +1258,6 @@ const ( FALLOC_FL_NO_HIDE_STALE = 0x4 FALLOC_FL_PUNCH_HOLE = 0x2 FALLOC_FL_UNSHARE_RANGE = 0x40 - FALLOC_FL_WRITE_ZEROES = 0x80 FALLOC_FL_ZERO_RANGE = 0x10 FANOTIFY_METADATA_VERSION = 0x3 FAN_ACCESS = 0x1 @@ -1489,7 +1477,6 @@ const ( GRND_INSECURE = 0x4 GRND_NONBLOCK = 0x1 GRND_RANDOM = 0x2 - GUEST_MEMFD_MAGIC = 0x474d454d HDIO_DRIVE_CMD = 0x31f HDIO_DRIVE_CMD_AEB = 0x31e HDIO_DRIVE_CMD_HDR_SIZE = 0x4 @@ -1530,7 +1517,6 @@ const ( HDIO_SET_XFER = 0x306 HDIO_TRISTATE_HWIF = 0x31b HDIO_UNREGISTER_HWIF = 0x32a - HIDIOCTL_LAST = 0xd HID_MAX_DESCRIPTOR_SIZE = 0x1000 HOSTFS_SUPER_MAGIC = 0xc0ffee HPFS_SUPER_MAGIC = 0xf995e849 @@ -1823,8 +1809,6 @@ const ( KEXEC_ARCH_X86_64 = 0x3e0000 KEXEC_CRASH_HOTPLUG_SUPPORT = 0x8 KEXEC_FILE_DEBUG = 0x8 - KEXEC_FILE_FORCE_DTB = 0x20 - KEXEC_FILE_NO_CMA = 0x10 KEXEC_FILE_NO_INITRAMFS = 0x4 KEXEC_FILE_ON_CRASH = 0x2 KEXEC_FILE_UNLOAD = 0x1 @@ -1921,7 +1905,6 @@ const ( LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON = 0x2 LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF = 0x1 LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF = 0x4 - LANDLOCK_RESTRICT_SELF_TSYNC = 0x8 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET = 0x1 LANDLOCK_SCOPE_SIGNAL = 0x2 LINUX_REBOOT_CMD_CAD_OFF = 0x0 @@ -2429,7 +2412,6 @@ const ( NN_PRXFPREG = "LINUX" NN_RISCV_CSR = "LINUX" NN_RISCV_TAGGED_ADDR_CTRL = "LINUX" - NN_RISCV_USER_CFI = "LINUX" NN_RISCV_VECTOR = "LINUX" NN_S390_CTRS = "LINUX" NN_S390_GS_BC = "LINUX" @@ -2511,7 +2493,6 @@ const ( NT_PRXFPREG = 0x46e62b7f NT_RISCV_CSR = 0x900 NT_RISCV_TAGGED_ADDR_CTRL = 0x902 - NT_RISCV_USER_CFI = 0x903 NT_RISCV_VECTOR = 0x901 NT_S390_CTRS = 0x304 NT_S390_GS_BC = 0x30c @@ -2534,7 +2515,6 @@ const ( NT_X86_SHSTK = 0x204 NT_X86_XSAVE_LAYOUT = 0x205 NT_X86_XSTATE = 0x202 - NULL_FS_MAGIC = 0x4e554c4c OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -2614,7 +2594,6 @@ const ( PERF_ATTR_SIZE_VER6 = 0x78 PERF_ATTR_SIZE_VER7 = 0x80 PERF_ATTR_SIZE_VER8 = 0x88 - PERF_ATTR_SIZE_VER9 = 0x90 PERF_AUX_FLAG_COLLISION = 0x8 PERF_AUX_FLAG_CORESIGHT_FORMAT_CORESIGHT = 0x0 PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW = 0x100 @@ -2650,7 +2629,6 @@ const ( PERF_MEM_LVLNUM_ANY_CACHE = 0xb PERF_MEM_LVLNUM_CXL = 0x9 PERF_MEM_LVLNUM_IO = 0xa - PERF_MEM_LVLNUM_L0 = 0x7 PERF_MEM_LVLNUM_L1 = 0x1 PERF_MEM_LVLNUM_L2 = 0x2 PERF_MEM_LVLNUM_L2_MHB = 0x5 @@ -2684,23 +2662,6 @@ const ( PERF_MEM_OP_PFETCH = 0x8 PERF_MEM_OP_SHIFT = 0x0 PERF_MEM_OP_STORE = 0x4 - PERF_MEM_REGION_L_NON_SHARE = 0x3 - PERF_MEM_REGION_L_SHARE = 0x2 - PERF_MEM_REGION_MEM0 = 0x8 - PERF_MEM_REGION_MEM1 = 0x9 - PERF_MEM_REGION_MEM2 = 0xa - PERF_MEM_REGION_MEM3 = 0xb - PERF_MEM_REGION_MEM4 = 0xc - PERF_MEM_REGION_MEM5 = 0xd - PERF_MEM_REGION_MEM6 = 0xe - PERF_MEM_REGION_MEM7 = 0xf - PERF_MEM_REGION_MMIO = 0x7 - PERF_MEM_REGION_NA = 0x0 - PERF_MEM_REGION_O_IO = 0x4 - PERF_MEM_REGION_O_NON_SHARE = 0x6 - PERF_MEM_REGION_O_SHARE = 0x5 - PERF_MEM_REGION_RSVD = 0x1 - PERF_MEM_REGION_SHIFT = 0x2e PERF_MEM_REMOTE_REMOTE = 0x1 PERF_MEM_REMOTE_SHIFT = 0x25 PERF_MEM_SNOOPX_FWD = 0x1 @@ -2815,10 +2776,6 @@ const ( PR_CAP_AMBIENT_IS_SET = 0x1 PR_CAP_AMBIENT_LOWER = 0x3 PR_CAP_AMBIENT_RAISE = 0x2 - PR_CFI_BRANCH_LANDING_PADS = 0x0 - PR_CFI_DISABLE = 0x2 - PR_CFI_ENABLE = 0x1 - PR_CFI_LOCK = 0x4 PR_ENDIAN_BIG = 0x0 PR_ENDIAN_LITTLE = 0x1 PR_ENDIAN_PPC_LITTLE = 0x2 @@ -2841,7 +2798,6 @@ const ( PR_FUTEX_HASH_GET_SLOTS = 0x2 PR_FUTEX_HASH_SET_SLOTS = 0x1 PR_GET_AUXV = 0x41555856 - PR_GET_CFI = 0x50 PR_GET_CHILD_SUBREAPER = 0x25 PR_GET_DUMPABLE = 0x3 PR_GET_ENDIAN = 0x13 @@ -2878,7 +2834,6 @@ const ( PR_MDWE_REFUSE_EXEC_GAIN = 0x1 PR_MPX_DISABLE_MANAGEMENT = 0x2c PR_MPX_ENABLE_MANAGEMENT = 0x2b - PR_MTE_STORE_ONLY = 0x80000 PR_MTE_TAG_MASK = 0x7fff8 PR_MTE_TAG_SHIFT = 0x3 PR_MTE_TCF_ASYNC = 0x4 @@ -2922,10 +2877,6 @@ const ( PR_RISCV_V_VSTATE_CTRL_NEXT_MASK = 0xc PR_RISCV_V_VSTATE_CTRL_OFF = 0x1 PR_RISCV_V_VSTATE_CTRL_ON = 0x2 - PR_RSEQ_SLICE_EXTENSION = 0x4f - PR_RSEQ_SLICE_EXTENSION_GET = 0x1 - PR_RSEQ_SLICE_EXTENSION_SET = 0x2 - PR_RSEQ_SLICE_EXT_ENABLE = 0x1 PR_SCHED_CORE = 0x3e PR_SCHED_CORE_CREATE = 0x1 PR_SCHED_CORE_GET = 0x0 @@ -2935,7 +2886,6 @@ const ( PR_SCHED_CORE_SCOPE_THREAD_GROUP = 0x1 PR_SCHED_CORE_SHARE_FROM = 0x3 PR_SCHED_CORE_SHARE_TO = 0x2 - PR_SET_CFI = 0x51 PR_SET_CHILD_SUBREAPER = 0x24 PR_SET_DUMPABLE = 0x4 PR_SET_ENDIAN = 0x14 @@ -3001,14 +2951,11 @@ const ( PR_SVE_SET_VL_ONEXEC = 0x40000 PR_SVE_VL_INHERIT = 0x20000 PR_SVE_VL_LEN_MASK = 0xffff - PR_SYS_DISPATCH_EXCLUSIVE_ON = 0x1 - PR_SYS_DISPATCH_INCLUSIVE_ON = 0x2 PR_SYS_DISPATCH_OFF = 0x0 PR_SYS_DISPATCH_ON = 0x1 PR_TAGGED_ADDR_ENABLE = 0x1 PR_TASK_PERF_EVENTS_DISABLE = 0x1f PR_TASK_PERF_EVENTS_ENABLE = 0x20 - PR_THP_DISABLE_EXCEPT_ADVISED = 0x2 PR_TIMER_CREATE_RESTORE_IDS = 0x4d PR_TIMER_CREATE_RESTORE_IDS_GET = 0x2 PR_TIMER_CREATE_RESTORE_IDS_OFF = 0x0 @@ -3040,10 +2987,8 @@ const ( PTP_STRICT_FLAGS = 0x8 PTP_SYS_OFFSET_EXTENDED = 0xc4c03d09 PTP_SYS_OFFSET_EXTENDED2 = 0xc4c03d12 - PTP_SYS_OFFSET_EXTENDED_CYCLES = 0xc4c03d16 PTP_SYS_OFFSET_PRECISE = 0xc0403d08 PTP_SYS_OFFSET_PRECISE2 = 0xc0403d11 - PTP_SYS_OFFSET_PRECISE_CYCLES = 0xc0403d15 PTRACE_ATTACH = 0x10 PTRACE_CONT = 0x7 PTRACE_DETACH = 0x11 @@ -3385,9 +3330,8 @@ const ( RWF_DSYNC = 0x2 RWF_HIPRI = 0x1 RWF_NOAPPEND = 0x20 - RWF_NOSIGNAL = 0x100 RWF_NOWAIT = 0x8 - RWF_SUPPORTED = 0x1ff + RWF_SUPPORTED = 0xff RWF_SYNC = 0x4 RWF_WRITE_LIFE_NOT_SET = 0x0 SCHED_BATCH = 0x3 @@ -3770,7 +3714,7 @@ const ( TASKSTATS_GENL_NAME = "TASKSTATS" TASKSTATS_GENL_VERSION = 0x1 TASKSTATS_TYPE_MAX = 0x6 - TASKSTATS_VERSION = 0x11 + TASKSTATS_VERSION = 0x10 TCIFLUSH = 0x0 TCIOFF = 0x2 TCIOFLUSH = 0x2 @@ -4108,7 +4052,6 @@ const ( XDP_FLAGS_REPLACE = 0x10 XDP_FLAGS_SKB_MODE = 0x2 XDP_FLAGS_UPDATE_IF_NOEXIST = 0x1 - XDP_MAX_TX_SKB_BUDGET = 0x9 XDP_MMAP_OFFSETS = 0x1 XDP_OPTIONS = 0x8 XDP_OPTIONS_ZEROCOPY = 0x1 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index c0a8ea1de..97a61fc5b 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -159,7 +159,6 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x8008b70d NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 @@ -306,7 +305,6 @@ const ( RTC_WKALM_SET = 0x4028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -354,7 +352,6 @@ const ( SO_ERROR = 0x4 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x9 SO_LINGER = 0xd SO_LOCK_FILTER = 0x2c @@ -599,8 +596,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -824,7 +819,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index ff927c830..a0d6d498c 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -159,7 +159,6 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x8008b70d NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 @@ -307,7 +306,6 @@ const ( RTC_WKALM_SET = 0x4028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -355,7 +353,6 @@ const ( SO_ERROR = 0x4 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x9 SO_LINGER = 0xd SO_LOCK_FILTER = 0x2c @@ -599,8 +596,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -824,7 +819,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 55294eda5..dd9c903f9 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -156,7 +156,6 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x8008b70d NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 @@ -312,7 +311,6 @@ const ( RTC_WKALM_SET = 0x4028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -360,7 +358,6 @@ const ( SO_ERROR = 0x4 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x9 SO_LINGER = 0xd SO_LOCK_FILTER = 0x2c @@ -604,8 +601,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -829,7 +824,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 5dac54c35..384c61ca3 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -161,7 +161,6 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x8008b70d NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 @@ -305,7 +304,6 @@ const ( RTC_WKALM_SET = 0x4028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -353,7 +351,6 @@ const ( SO_ERROR = 0x4 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x9 SO_LINGER = 0xd SO_LOCK_FILTER = 0x2c @@ -601,8 +598,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -826,7 +821,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index 46ac1fcb2..6384c9831 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -160,7 +160,6 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x8008b70d NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 @@ -299,7 +298,6 @@ const ( RTC_WKALM_SET = 0x4028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -347,7 +345,6 @@ const ( SO_ERROR = 0x4 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x9 SO_LINGER = 0xd SO_LOCK_FILTER = 0x2c @@ -591,8 +588,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -816,7 +811,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index b55483e8a..553c1c6f1 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -156,7 +156,6 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x4008b70d NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 @@ -305,7 +304,6 @@ const ( RTC_WKALM_SET = 0x8028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -353,7 +351,6 @@ const ( SO_ERROR = 0x1007 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x8 SO_LINGER = 0x80 SO_LOCK_FILTER = 0x2c @@ -600,8 +597,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x60) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x46d) - EFSBADCRC = syscall.Errno(0x4d) - EFSCORRUPTED = syscall.Errno(0x87) EHOSTDOWN = syscall.Errno(0x93) EHOSTUNREACH = syscall.Errno(0x94) EHWPOISON = syscall.Errno(0xa8) @@ -819,7 +814,7 @@ var errorList = [...]struct { {132, "ENOBUFS", "no buffer space available"}, {133, "EISCONN", "transport endpoint is already connected"}, {134, "ENOTCONN", "transport endpoint is not connected"}, - {135, "EFSCORRUPTED", "structure needs cleaning"}, + {135, "EUCLEAN", "structure needs cleaning"}, {137, "ENOTNAM", "not a XENIX named type file"}, {138, "ENAVAIL", "no XENIX semaphores available"}, {139, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 71890c98a..b3339f209 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -156,7 +156,6 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x4008b70d NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 @@ -305,7 +304,6 @@ const ( RTC_WKALM_SET = 0x8028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -353,7 +351,6 @@ const ( SO_ERROR = 0x1007 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x8 SO_LINGER = 0x80 SO_LOCK_FILTER = 0x2c @@ -600,8 +597,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x60) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x46d) - EFSBADCRC = syscall.Errno(0x4d) - EFSCORRUPTED = syscall.Errno(0x87) EHOSTDOWN = syscall.Errno(0x93) EHOSTUNREACH = syscall.Errno(0x94) EHWPOISON = syscall.Errno(0xa8) @@ -819,7 +814,7 @@ var errorList = [...]struct { {132, "ENOBUFS", "no buffer space available"}, {133, "EISCONN", "transport endpoint is already connected"}, {134, "ENOTCONN", "transport endpoint is not connected"}, - {135, "EFSCORRUPTED", "structure needs cleaning"}, + {135, "EUCLEAN", "structure needs cleaning"}, {137, "ENOTNAM", "not a XENIX named type file"}, {138, "ENAVAIL", "no XENIX semaphores available"}, {139, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index a78b6cc14..177091d2b 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -156,7 +156,6 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x4008b70d NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 @@ -305,7 +304,6 @@ const ( RTC_WKALM_SET = 0x8028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -353,7 +351,6 @@ const ( SO_ERROR = 0x1007 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x8 SO_LINGER = 0x80 SO_LOCK_FILTER = 0x2c @@ -600,8 +597,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x60) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x46d) - EFSBADCRC = syscall.Errno(0x4d) - EFSCORRUPTED = syscall.Errno(0x87) EHOSTDOWN = syscall.Errno(0x93) EHOSTUNREACH = syscall.Errno(0x94) EHWPOISON = syscall.Errno(0xa8) @@ -819,7 +814,7 @@ var errorList = [...]struct { {132, "ENOBUFS", "no buffer space available"}, {133, "EISCONN", "transport endpoint is already connected"}, {134, "ENOTCONN", "transport endpoint is not connected"}, - {135, "EFSCORRUPTED", "structure needs cleaning"}, + {135, "EUCLEAN", "structure needs cleaning"}, {137, "ENOTNAM", "not a XENIX named type file"}, {138, "ENAVAIL", "no XENIX semaphores available"}, {139, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index d0e38ca73..c5abf156d 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -156,7 +156,6 @@ const ( NFDBITS = 0x20 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x4008b70d NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 @@ -305,7 +304,6 @@ const ( RTC_WKALM_SET = 0x8028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -353,7 +351,6 @@ const ( SO_ERROR = 0x1007 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x8 SO_LINGER = 0x80 SO_LOCK_FILTER = 0x2c @@ -600,8 +597,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x60) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x46d) - EFSBADCRC = syscall.Errno(0x4d) - EFSCORRUPTED = syscall.Errno(0x87) EHOSTDOWN = syscall.Errno(0x93) EHOSTUNREACH = syscall.Errno(0x94) EHWPOISON = syscall.Errno(0xa8) @@ -819,7 +814,7 @@ var errorList = [...]struct { {132, "ENOBUFS", "no buffer space available"}, {133, "EISCONN", "transport endpoint is already connected"}, {134, "ENOTCONN", "transport endpoint is not connected"}, - {135, "EFSCORRUPTED", "structure needs cleaning"}, + {135, "EUCLEAN", "structure needs cleaning"}, {137, "ENOTNAM", "not a XENIX named type file"}, {138, "ENAVAIL", "no XENIX semaphores available"}, {139, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index c883e14c7..f1f3fadf5 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -158,7 +158,6 @@ const ( NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 - NS_GET_ID = 0x4008b70d NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 @@ -360,7 +359,6 @@ const ( RTC_WKALM_SET = 0x8028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -408,7 +406,6 @@ const ( SO_ERROR = 0x4 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x9 SO_LINGER = 0xd SO_LOCK_FILTER = 0x2c @@ -656,8 +653,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -882,7 +877,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 1834273d4..203ad9c54 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -158,7 +158,6 @@ const ( NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 - NS_GET_ID = 0x4008b70d NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 @@ -364,7 +363,6 @@ const ( RTC_WKALM_SET = 0x8028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -412,7 +410,6 @@ const ( SO_ERROR = 0x4 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x9 SO_LINGER = 0xd SO_LOCK_FILTER = 0x2c @@ -660,8 +657,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -886,7 +881,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 39945dd9a..4b9abcb21 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -158,7 +158,6 @@ const ( NL3 = 0x300 NLDLY = 0x300 NOFLSH = 0x80000000 - NS_GET_ID = 0x4008b70d NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 @@ -364,7 +363,6 @@ const ( RTC_WKALM_SET = 0x8028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -412,7 +410,6 @@ const ( SO_ERROR = 0x4 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x9 SO_LINGER = 0xd SO_LOCK_FILTER = 0x2c @@ -660,8 +657,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -886,7 +881,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index bc0f37241..f87983037 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -11,569 +11,553 @@ package unix import "syscall" const ( - B1000000 = 0x1008 - B115200 = 0x1002 - B1152000 = 0x1009 - B1500000 = 0x100a - B2000000 = 0x100b - B230400 = 0x1003 - B2500000 = 0x100c - B3000000 = 0x100d - B3500000 = 0x100e - B4000000 = 0x100f - B460800 = 0x1004 - B500000 = 0x1005 - B57600 = 0x1001 - B576000 = 0x1006 - B921600 = 0x1007 - BLKALIGNOFF = 0x127a - BLKBSZGET = 0x80081270 - BLKBSZSET = 0x40081271 - BLKDISCARD = 0x1277 - BLKDISCARDZEROES = 0x127c - BLKFLSBUF = 0x1261 - BLKFRAGET = 0x1265 - BLKFRASET = 0x1264 - BLKGETDISKSEQ = 0x80081280 - BLKGETSIZE = 0x1260 - BLKGETSIZE64 = 0x80081272 - BLKIOMIN = 0x1278 - BLKIOOPT = 0x1279 - BLKPBSZGET = 0x127b - BLKRAGET = 0x1263 - BLKRASET = 0x1262 - BLKROGET = 0x125e - BLKROSET = 0x125d - BLKROTATIONAL = 0x127e - BLKRRPART = 0x125f - BLKSECDISCARD = 0x127d - BLKSECTGET = 0x1267 - BLKSECTSET = 0x1266 - BLKSSZGET = 0x1268 - BLKZEROOUT = 0x127f - BOTHER = 0x1000 - BS1 = 0x2000 - BSDLY = 0x2000 - CBAUD = 0x100f - CBAUDEX = 0x1000 - CIBAUD = 0x100f0000 - CLOCAL = 0x800 - CR1 = 0x200 - CR2 = 0x400 - CR3 = 0x600 - CRDLY = 0x600 - CREAD = 0x80 - CS6 = 0x10 - CS7 = 0x20 - CS8 = 0x30 - CSIZE = 0x30 - CSTOPB = 0x40 - DM_MPATH_PROBE_PATHS = 0xfd12 - ECCGETLAYOUT = 0x81484d11 - ECCGETSTATS = 0x80104d12 - ECHOCTL = 0x200 - ECHOE = 0x10 - ECHOK = 0x20 - ECHOKE = 0x800 - ECHONL = 0x40 - ECHOPRT = 0x400 - EFD_CLOEXEC = 0x80000 - EFD_NONBLOCK = 0x800 - EPIOCGPARAMS = 0x80088a02 - EPIOCSPARAMS = 0x40088a01 - EPOLL_CLOEXEC = 0x80000 - EXTPROC = 0x10000 - FF1 = 0x8000 - FFDLY = 0x8000 - FICLONE = 0x40049409 - FICLONERANGE = 0x4020940d - FLUSHO = 0x1000 - FS_IOC_ENABLE_VERITY = 0x40806685 - FS_IOC_GETFLAGS = 0x80086601 - FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b - FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 - FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 - FS_IOC_SETFLAGS = 0x40086602 - FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 - F_GETLK = 0x5 - F_GETLK64 = 0x5 - F_GETOWN = 0x9 - F_RDLCK = 0x0 - F_SETLK = 0x6 - F_SETLK64 = 0x6 - F_SETLKW = 0x7 - F_SETLKW64 = 0x7 - F_SETOWN = 0x8 - F_UNLCK = 0x2 - F_WRLCK = 0x1 - HIDIOCGRAWINFO = 0x80084803 - HIDIOCGRDESC = 0x90044802 - HIDIOCGRDESCSIZE = 0x80044801 - HIDIOCREVOKE = 0x4004480d - HUPCL = 0x400 - ICANON = 0x2 - IEXTEN = 0x8000 - IN_CLOEXEC = 0x80000 - IN_NONBLOCK = 0x800 - IOCTL_MEI_NOTIFY_GET = 0x80044803 - IOCTL_MEI_NOTIFY_SET = 0x40044802 - IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 - IPV6_FLOWINFO_MASK = 0xffffff0f - IPV6_FLOWLABEL_MASK = 0xffff0f00 - ISIG = 0x1 - IUCLC = 0x200 - IXOFF = 0x1000 - IXON = 0x400 - MAP_ANON = 0x20 - MAP_ANONYMOUS = 0x20 - MAP_DENYWRITE = 0x800 - MAP_EXECUTABLE = 0x1000 - MAP_GROWSDOWN = 0x100 - MAP_HUGETLB = 0x40000 - MAP_LOCKED = 0x2000 - MAP_NONBLOCK = 0x10000 - MAP_NORESERVE = 0x4000 - MAP_POPULATE = 0x8000 - MAP_STACK = 0x20000 - MAP_SYNC = 0x80000 - MCL_CURRENT = 0x1 - MCL_FUTURE = 0x2 - MCL_ONFAULT = 0x4 - MEMERASE = 0x40084d02 - MEMERASE64 = 0x40104d14 - MEMGETBADBLOCK = 0x40084d0b - MEMGETINFO = 0x80204d01 - MEMGETOOBSEL = 0x80c84d0a - MEMGETREGIONCOUNT = 0x80044d07 - MEMISLOCKED = 0x80084d17 - MEMLOCK = 0x40084d05 - MEMREAD = 0xc0404d1a - MEMREADOOB = 0xc0104d04 - MEMSETBADBLOCK = 0x40084d0c - MEMUNLOCK = 0x40084d06 - MEMWRITEOOB = 0xc0104d03 - MTDFILEMODE = 0x4d13 - NFDBITS = 0x40 - NLDLY = 0x100 - NOFLSH = 0x80 - NS_GET_ID = 0x8008b70d - NS_GET_MNTNS_ID = 0x8008b705 - NS_GET_NSTYPE = 0xb703 - NS_GET_OWNER_UID = 0xb704 - NS_GET_PARENT = 0xb702 - NS_GET_PID_FROM_PIDNS = 0x8004b706 - NS_GET_PID_IN_PIDNS = 0x8004b708 - NS_GET_TGID_FROM_PIDNS = 0x8004b707 - NS_GET_TGID_IN_PIDNS = 0x8004b709 - NS_GET_USERNS = 0xb701 - OLCUC = 0x2 - ONLCR = 0x4 - OTPERASE = 0x400c4d19 - OTPGETREGIONCOUNT = 0x40044d0e - OTPGETREGIONINFO = 0x400c4d0f - OTPLOCK = 0x800c4d10 - OTPSELECT = 0x80044d0d - O_APPEND = 0x400 - O_ASYNC = 0x2000 - O_CLOEXEC = 0x80000 - O_CREAT = 0x40 - O_DIRECT = 0x4000 - O_DIRECTORY = 0x10000 - O_DSYNC = 0x1000 - O_EXCL = 0x80 - O_FSYNC = 0x101000 - O_LARGEFILE = 0x0 - O_NDELAY = 0x800 - O_NOATIME = 0x40000 - O_NOCTTY = 0x100 - O_NOFOLLOW = 0x20000 - O_NONBLOCK = 0x800 - O_PATH = 0x200000 - O_RSYNC = 0x101000 - O_SYNC = 0x101000 - O_TMPFILE = 0x410000 - O_TRUNC = 0x200 - PARENB = 0x100 - PARODD = 0x200 - PENDIN = 0x4000 - PERF_EVENT_IOC_DISABLE = 0x2401 - PERF_EVENT_IOC_ENABLE = 0x2400 - PERF_EVENT_IOC_ID = 0x80082407 - PERF_EVENT_IOC_MODIFY_ATTRIBUTES = 0x4008240b - PERF_EVENT_IOC_PAUSE_OUTPUT = 0x40042409 - PERF_EVENT_IOC_PERIOD = 0x40082404 - PERF_EVENT_IOC_QUERY_BPF = 0xc008240a - PERF_EVENT_IOC_REFRESH = 0x2402 - PERF_EVENT_IOC_RESET = 0x2403 - PERF_EVENT_IOC_SET_BPF = 0x40042408 - PERF_EVENT_IOC_SET_FILTER = 0x40082406 - PERF_EVENT_IOC_SET_OUTPUT = 0x2405 - PPPIOCATTACH = 0x4004743d - PPPIOCATTCHAN = 0x40047438 - PPPIOCBRIDGECHAN = 0x40047435 - PPPIOCCONNECT = 0x4004743a - PPPIOCDETACH = 0x4004743c - PPPIOCDISCONN = 0x7439 - PPPIOCGASYNCMAP = 0x80047458 - PPPIOCGCHAN = 0x80047437 - PPPIOCGDEBUG = 0x80047441 - PPPIOCGFLAGS = 0x8004745a - PPPIOCGIDLE = 0x8010743f - PPPIOCGIDLE32 = 0x8008743f - PPPIOCGIDLE64 = 0x8010743f - PPPIOCGL2TPSTATS = 0x80487436 - PPPIOCGMRU = 0x80047453 - PPPIOCGRASYNCMAP = 0x80047455 - PPPIOCGUNIT = 0x80047456 - PPPIOCGXASYNCMAP = 0x80207450 - PPPIOCSACTIVE = 0x40107446 - PPPIOCSASYNCMAP = 0x40047457 - PPPIOCSCOMPRESS = 0x4010744d - PPPIOCSDEBUG = 0x40047440 - PPPIOCSFLAGS = 0x40047459 - PPPIOCSMAXCID = 0x40047451 - PPPIOCSMRRU = 0x4004743b - PPPIOCSMRU = 0x40047452 - PPPIOCSNPMODE = 0x4008744b - PPPIOCSPASS = 0x40107447 - PPPIOCSRASYNCMAP = 0x40047454 - PPPIOCSXASYNCMAP = 0x4020744f - PPPIOCUNBRIDGECHAN = 0x7434 - PPPIOCXFERUNIT = 0x744e - PR_SET_PTRACER_ANY = 0xffffffffffffffff - PTP_CLOCK_GETCAPS = 0x80503d01 - PTP_CLOCK_GETCAPS2 = 0x80503d0a - PTP_ENABLE_PPS = 0x40043d04 - PTP_ENABLE_PPS2 = 0x40043d0d - PTP_EXTTS_REQUEST = 0x40103d02 - PTP_EXTTS_REQUEST2 = 0x40103d0b - PTP_MASK_CLEAR_ALL = 0x3d13 - PTP_MASK_EN_SINGLE = 0x40043d14 - PTP_PEROUT_REQUEST = 0x40383d03 - PTP_PEROUT_REQUEST2 = 0x40383d0c - PTP_PIN_SETFUNC = 0x40603d07 - PTP_PIN_SETFUNC2 = 0x40603d10 - PTP_SYS_OFFSET = 0x43403d05 - PTP_SYS_OFFSET2 = 0x43403d0e - PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_BIT = 0x2 - PTRACE_CFI_BRANCH_EXPECTED_LANDING_PAD_STATE = 0x4 - PTRACE_CFI_BRANCH_LANDING_PAD_EN_BIT = 0x0 - PTRACE_CFI_BRANCH_LANDING_PAD_EN_STATE = 0x1 - PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_BIT = 0x1 - PTRACE_CFI_BRANCH_LANDING_PAD_LOCK_STATE = 0x2 - PTRACE_CFI_SHADOW_STACK_EN_BIT = 0x3 - PTRACE_CFI_SHADOW_STACK_EN_STATE = 0x8 - PTRACE_CFI_SHADOW_STACK_LOCK_BIT = 0x4 - PTRACE_CFI_SHADOW_STACK_LOCK_STATE = 0x10 - PTRACE_CFI_SHADOW_STACK_PTR_BIT = 0x5 - PTRACE_CFI_SHADOW_STACK_PTR_STATE = 0x20 - PTRACE_CFI_STATE_INVALID_MASK = 0xffffffffffffffc0 - PTRACE_GETFDPIC = 0x21 - PTRACE_GETFDPIC_EXEC = 0x0 - PTRACE_GETFDPIC_INTERP = 0x1 - RLIMIT_AS = 0x9 - RLIMIT_MEMLOCK = 0x8 - RLIMIT_NOFILE = 0x7 - RLIMIT_NPROC = 0x6 - RLIMIT_RSS = 0x5 - RNDADDENTROPY = 0x40085203 - RNDADDTOENTCNT = 0x40045201 - RNDCLEARPOOL = 0x5206 - RNDGETENTCNT = 0x80045200 - RNDGETPOOL = 0x80085202 - RNDRESEEDCRNG = 0x5207 - RNDZAPENTCNT = 0x5204 - RTC_AIE_OFF = 0x7002 - RTC_AIE_ON = 0x7001 - RTC_ALM_READ = 0x80247008 - RTC_ALM_SET = 0x40247007 - RTC_EPOCH_READ = 0x8008700d - RTC_EPOCH_SET = 0x4008700e - RTC_IRQP_READ = 0x8008700b - RTC_IRQP_SET = 0x4008700c - RTC_PARAM_GET = 0x40187013 - RTC_PARAM_SET = 0x40187014 - RTC_PIE_OFF = 0x7006 - RTC_PIE_ON = 0x7005 - RTC_PLL_GET = 0x80207011 - RTC_PLL_SET = 0x40207012 - RTC_RD_TIME = 0x80247009 - RTC_SET_TIME = 0x4024700a - RTC_UIE_OFF = 0x7004 - RTC_UIE_ON = 0x7003 - RTC_VL_CLR = 0x7014 - RTC_VL_READ = 0x80047013 - RTC_WIE_OFF = 0x7010 - RTC_WIE_ON = 0x700f - RTC_WKALM_RD = 0x80287010 - RTC_WKALM_SET = 0x4028700f - SCM_DEVMEM_DMABUF = 0x4f - SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 - SCM_TIMESTAMPING = 0x25 - SCM_TIMESTAMPING_OPT_STATS = 0x36 - SCM_TIMESTAMPING_PKTINFO = 0x3a - SCM_TIMESTAMPNS = 0x23 - SCM_TS_OPT_ID = 0x51 - SCM_TXTIME = 0x3d - SCM_WIFI_STATUS = 0x29 - SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 - SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 - SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 - SFD_CLOEXEC = 0x80000 - SFD_NONBLOCK = 0x800 - SIOCATMARK = 0x8905 - SIOCGPGRP = 0x8904 - SIOCGSTAMPNS_NEW = 0x80108907 - SIOCGSTAMP_NEW = 0x80108906 - SIOCINQ = 0x541b - SIOCOUTQ = 0x5411 - SIOCSPGRP = 0x8902 - SOCK_CLOEXEC = 0x80000 - SOCK_DGRAM = 0x2 - SOCK_NONBLOCK = 0x800 - SOCK_STREAM = 0x1 - SOL_SOCKET = 0x1 - SO_ACCEPTCONN = 0x1e - SO_ATTACH_BPF = 0x32 - SO_ATTACH_REUSEPORT_CBPF = 0x33 - SO_ATTACH_REUSEPORT_EBPF = 0x34 - SO_BINDTODEVICE = 0x19 - SO_BINDTOIFINDEX = 0x3e - SO_BPF_EXTENSIONS = 0x30 - SO_BROADCAST = 0x6 - SO_BSDCOMPAT = 0xe - SO_BUF_LOCK = 0x48 - SO_BUSY_POLL = 0x2e - SO_BUSY_POLL_BUDGET = 0x46 - SO_CNX_ADVICE = 0x35 - SO_COOKIE = 0x39 - SO_DETACH_REUSEPORT_BPF = 0x44 - SO_DEVMEM_DMABUF = 0x4f - SO_DEVMEM_DONTNEED = 0x50 - SO_DEVMEM_LINEAR = 0x4e - SO_DOMAIN = 0x27 - SO_DONTROUTE = 0x5 - SO_ERROR = 0x4 - SO_INCOMING_CPU = 0x31 - SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 - SO_KEEPALIVE = 0x9 - SO_LINGER = 0xd - SO_LOCK_FILTER = 0x2c - SO_MARK = 0x24 - SO_MAX_PACING_RATE = 0x2f - SO_MEMINFO = 0x37 - SO_NETNS_COOKIE = 0x47 - SO_NOFCS = 0x2b - SO_OOBINLINE = 0xa - SO_PASSCRED = 0x10 - SO_PASSPIDFD = 0x4c - SO_PASSRIGHTS = 0x53 - SO_PASSSEC = 0x22 - SO_PEEK_OFF = 0x2a - SO_PEERCRED = 0x11 - SO_PEERGROUPS = 0x3b - SO_PEERPIDFD = 0x4d - SO_PEERSEC = 0x1f - SO_PREFER_BUSY_POLL = 0x45 - SO_PROTOCOL = 0x26 - SO_RCVBUF = 0x8 - SO_RCVBUFFORCE = 0x21 - SO_RCVLOWAT = 0x12 - SO_RCVMARK = 0x4b - SO_RCVPRIORITY = 0x52 - SO_RCVTIMEO = 0x14 - SO_RCVTIMEO_NEW = 0x42 - SO_RCVTIMEO_OLD = 0x14 - SO_RESERVE_MEM = 0x49 - SO_REUSEADDR = 0x2 - SO_REUSEPORT = 0xf - SO_RXQ_OVFL = 0x28 - SO_SECURITY_AUTHENTICATION = 0x16 - SO_SECURITY_ENCRYPTION_NETWORK = 0x18 - SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17 - SO_SELECT_ERR_QUEUE = 0x2d - SO_SNDBUF = 0x7 - SO_SNDBUFFORCE = 0x20 - SO_SNDLOWAT = 0x13 - SO_SNDTIMEO = 0x15 - SO_SNDTIMEO_NEW = 0x43 - SO_SNDTIMEO_OLD = 0x15 - SO_TIMESTAMPING = 0x25 - SO_TIMESTAMPING_NEW = 0x41 - SO_TIMESTAMPING_OLD = 0x25 - SO_TIMESTAMPNS = 0x23 - SO_TIMESTAMPNS_NEW = 0x40 - SO_TIMESTAMPNS_OLD = 0x23 - SO_TIMESTAMP_NEW = 0x3f - SO_TXREHASH = 0x4a - SO_TXTIME = 0x3d - SO_TYPE = 0x3 - SO_WIFI_STATUS = 0x29 - SO_ZEROCOPY = 0x3c - TAB1 = 0x800 - TAB2 = 0x1000 - TAB3 = 0x1800 - TABDLY = 0x1800 - TCFLSH = 0x540b - TCGETA = 0x5405 - TCGETS = 0x5401 - TCGETS2 = 0x802c542a - TCGETX = 0x5432 - TCSAFLUSH = 0x2 - TCSBRK = 0x5409 - TCSBRKP = 0x5425 - TCSETA = 0x5406 - TCSETAF = 0x5408 - TCSETAW = 0x5407 - TCSETS = 0x5402 - TCSETS2 = 0x402c542b - TCSETSF = 0x5404 - TCSETSF2 = 0x402c542d - TCSETSW = 0x5403 - TCSETSW2 = 0x402c542c - TCSETX = 0x5433 - TCSETXF = 0x5434 - TCSETXW = 0x5435 - TCXONC = 0x540a - TFD_CLOEXEC = 0x80000 - TFD_NONBLOCK = 0x800 - TIOCCBRK = 0x5428 - TIOCCONS = 0x541d - TIOCEXCL = 0x540c - TIOCGDEV = 0x80045432 - TIOCGETD = 0x5424 - TIOCGEXCL = 0x80045440 - TIOCGICOUNT = 0x545d - TIOCGISO7816 = 0x80285442 - TIOCGLCKTRMIOS = 0x5456 - TIOCGPGRP = 0x540f - TIOCGPKT = 0x80045438 - TIOCGPTLCK = 0x80045439 - TIOCGPTN = 0x80045430 - TIOCGPTPEER = 0x5441 - TIOCGRS485 = 0x542e - TIOCGSERIAL = 0x541e - TIOCGSID = 0x5429 - TIOCGSOFTCAR = 0x5419 - TIOCGWINSZ = 0x5413 - TIOCINQ = 0x541b - TIOCLINUX = 0x541c - TIOCMBIC = 0x5417 - TIOCMBIS = 0x5416 - TIOCMGET = 0x5415 - TIOCMIWAIT = 0x545c - TIOCMSET = 0x5418 - TIOCM_CAR = 0x40 - TIOCM_CD = 0x40 - TIOCM_CTS = 0x20 - TIOCM_DSR = 0x100 - TIOCM_RI = 0x80 - TIOCM_RNG = 0x80 - TIOCM_SR = 0x10 - TIOCM_ST = 0x8 - TIOCNOTTY = 0x5422 - TIOCNXCL = 0x540d - TIOCOUTQ = 0x5411 - TIOCPKT = 0x5420 - TIOCSBRK = 0x5427 - TIOCSCTTY = 0x540e - TIOCSERCONFIG = 0x5453 - TIOCSERGETLSR = 0x5459 - TIOCSERGETMULTI = 0x545a - TIOCSERGSTRUCT = 0x5458 - TIOCSERGWILD = 0x5454 - TIOCSERSETMULTI = 0x545b - TIOCSERSWILD = 0x5455 - TIOCSER_TEMT = 0x1 - TIOCSETD = 0x5423 - TIOCSIG = 0x40045436 - TIOCSISO7816 = 0xc0285443 - TIOCSLCKTRMIOS = 0x5457 - TIOCSPGRP = 0x5410 - TIOCSPTLCK = 0x40045431 - TIOCSRS485 = 0x542f - TIOCSSERIAL = 0x541f - TIOCSSOFTCAR = 0x541a - TIOCSTI = 0x5412 - TIOCSWINSZ = 0x5414 - TIOCVHANGUP = 0x5437 - TOSTOP = 0x100 - TUNATTACHFILTER = 0x401054d5 - TUNDETACHFILTER = 0x401054d6 - TUNGETDEVNETNS = 0x54e3 - TUNGETFEATURES = 0x800454cf - TUNGETFILTER = 0x801054db - TUNGETIFF = 0x800454d2 - TUNGETSNDBUF = 0x800454d3 - TUNGETVNETBE = 0x800454df - TUNGETVNETHDRSZ = 0x800454d7 - TUNGETVNETLE = 0x800454dd - TUNSETCARRIER = 0x400454e2 - TUNSETDEBUG = 0x400454c9 - TUNSETFILTEREBPF = 0x800454e1 - TUNSETGROUP = 0x400454ce - TUNSETIFF = 0x400454ca - TUNSETIFINDEX = 0x400454da - TUNSETLINK = 0x400454cd - TUNSETNOCSUM = 0x400454c8 - TUNSETOFFLOAD = 0x400454d0 - TUNSETOWNER = 0x400454cc - TUNSETPERSIST = 0x400454cb - TUNSETQUEUE = 0x400454d9 - TUNSETSNDBUF = 0x400454d4 - TUNSETSTEERINGEBPF = 0x800454e0 - TUNSETTXFILTER = 0x400454d1 - TUNSETVNETBE = 0x400454de - TUNSETVNETHDRSZ = 0x400454d8 - TUNSETVNETLE = 0x400454dc - UBI_IOCATT = 0x40186f40 - UBI_IOCDET = 0x40046f41 - UBI_IOCEBCH = 0x40044f02 - UBI_IOCEBER = 0x40044f01 - UBI_IOCEBISMAP = 0x80044f05 - UBI_IOCEBMAP = 0x40084f03 - UBI_IOCEBUNMAP = 0x40044f04 - UBI_IOCMKVOL = 0x40986f00 - UBI_IOCRMVOL = 0x40046f01 - UBI_IOCRNVOL = 0x51106f03 - UBI_IOCRPEB = 0x40046f04 - UBI_IOCRSVOL = 0x400c6f02 - UBI_IOCSETVOLPROP = 0x40104f06 - UBI_IOCSPEB = 0x40046f05 - UBI_IOCVOLCRBLK = 0x40804f07 - UBI_IOCVOLRMBLK = 0x4f08 - UBI_IOCVOLUP = 0x40084f00 - VDISCARD = 0xd - VEOF = 0x4 - VEOL = 0xb - VEOL2 = 0x10 - VMIN = 0x6 - VREPRINT = 0xc - VSTART = 0x8 - VSTOP = 0x9 - VSUSP = 0xa - VSWTC = 0x7 - VT1 = 0x4000 - VTDLY = 0x4000 - VTIME = 0x5 - VWERASE = 0xe - WDIOC_GETBOOTSTATUS = 0x80045702 - WDIOC_GETPRETIMEOUT = 0x80045709 - WDIOC_GETSTATUS = 0x80045701 - WDIOC_GETSUPPORT = 0x80285700 - WDIOC_GETTEMP = 0x80045703 - WDIOC_GETTIMELEFT = 0x8004570a - WDIOC_GETTIMEOUT = 0x80045707 - WDIOC_KEEPALIVE = 0x80045705 - WDIOC_SETOPTIONS = 0x80045704 - WORDSIZE = 0x40 - XCASE = 0x4 - XTABS = 0x1800 - _HIDIOCGRAWNAME = 0x80804804 - _HIDIOCGRAWPHYS = 0x80404805 - _HIDIOCGRAWUNIQ = 0x80404808 + B1000000 = 0x1008 + B115200 = 0x1002 + B1152000 = 0x1009 + B1500000 = 0x100a + B2000000 = 0x100b + B230400 = 0x1003 + B2500000 = 0x100c + B3000000 = 0x100d + B3500000 = 0x100e + B4000000 = 0x100f + B460800 = 0x1004 + B500000 = 0x1005 + B57600 = 0x1001 + B576000 = 0x1006 + B921600 = 0x1007 + BLKALIGNOFF = 0x127a + BLKBSZGET = 0x80081270 + BLKBSZSET = 0x40081271 + BLKDISCARD = 0x1277 + BLKDISCARDZEROES = 0x127c + BLKFLSBUF = 0x1261 + BLKFRAGET = 0x1265 + BLKFRASET = 0x1264 + BLKGETDISKSEQ = 0x80081280 + BLKGETSIZE = 0x1260 + BLKGETSIZE64 = 0x80081272 + BLKIOMIN = 0x1278 + BLKIOOPT = 0x1279 + BLKPBSZGET = 0x127b + BLKRAGET = 0x1263 + BLKRASET = 0x1262 + BLKROGET = 0x125e + BLKROSET = 0x125d + BLKROTATIONAL = 0x127e + BLKRRPART = 0x125f + BLKSECDISCARD = 0x127d + BLKSECTGET = 0x1267 + BLKSECTSET = 0x1266 + BLKSSZGET = 0x1268 + BLKZEROOUT = 0x127f + BOTHER = 0x1000 + BS1 = 0x2000 + BSDLY = 0x2000 + CBAUD = 0x100f + CBAUDEX = 0x1000 + CIBAUD = 0x100f0000 + CLOCAL = 0x800 + CR1 = 0x200 + CR2 = 0x400 + CR3 = 0x600 + CRDLY = 0x600 + CREAD = 0x80 + CS6 = 0x10 + CS7 = 0x20 + CS8 = 0x30 + CSIZE = 0x30 + CSTOPB = 0x40 + DM_MPATH_PROBE_PATHS = 0xfd12 + ECCGETLAYOUT = 0x81484d11 + ECCGETSTATS = 0x80104d12 + ECHOCTL = 0x200 + ECHOE = 0x10 + ECHOK = 0x20 + ECHOKE = 0x800 + ECHONL = 0x40 + ECHOPRT = 0x400 + EFD_CLOEXEC = 0x80000 + EFD_NONBLOCK = 0x800 + EPIOCGPARAMS = 0x80088a02 + EPIOCSPARAMS = 0x40088a01 + EPOLL_CLOEXEC = 0x80000 + EXTPROC = 0x10000 + FF1 = 0x8000 + FFDLY = 0x8000 + FICLONE = 0x40049409 + FICLONERANGE = 0x4020940d + FLUSHO = 0x1000 + FS_IOC_ENABLE_VERITY = 0x40806685 + FS_IOC_GETFLAGS = 0x80086601 + FS_IOC_GET_ENCRYPTION_NONCE = 0x8010661b + FS_IOC_GET_ENCRYPTION_POLICY = 0x400c6615 + FS_IOC_GET_ENCRYPTION_PWSALT = 0x40106614 + FS_IOC_SETFLAGS = 0x40086602 + FS_IOC_SET_ENCRYPTION_POLICY = 0x800c6613 + F_GETLK = 0x5 + F_GETLK64 = 0x5 + F_GETOWN = 0x9 + F_RDLCK = 0x0 + F_SETLK = 0x6 + F_SETLK64 = 0x6 + F_SETLKW = 0x7 + F_SETLKW64 = 0x7 + F_SETOWN = 0x8 + F_UNLCK = 0x2 + F_WRLCK = 0x1 + HIDIOCGRAWINFO = 0x80084803 + HIDIOCGRDESC = 0x90044802 + HIDIOCGRDESCSIZE = 0x80044801 + HIDIOCREVOKE = 0x4004480d + HUPCL = 0x400 + ICANON = 0x2 + IEXTEN = 0x8000 + IN_CLOEXEC = 0x80000 + IN_NONBLOCK = 0x800 + IOCTL_MEI_NOTIFY_GET = 0x80044803 + IOCTL_MEI_NOTIFY_SET = 0x40044802 + IOCTL_VM_SOCKETS_GET_LOCAL_CID = 0x7b9 + IPV6_FLOWINFO_MASK = 0xffffff0f + IPV6_FLOWLABEL_MASK = 0xffff0f00 + ISIG = 0x1 + IUCLC = 0x200 + IXOFF = 0x1000 + IXON = 0x400 + MAP_ANON = 0x20 + MAP_ANONYMOUS = 0x20 + MAP_DENYWRITE = 0x800 + MAP_EXECUTABLE = 0x1000 + MAP_GROWSDOWN = 0x100 + MAP_HUGETLB = 0x40000 + MAP_LOCKED = 0x2000 + MAP_NONBLOCK = 0x10000 + MAP_NORESERVE = 0x4000 + MAP_POPULATE = 0x8000 + MAP_STACK = 0x20000 + MAP_SYNC = 0x80000 + MCL_CURRENT = 0x1 + MCL_FUTURE = 0x2 + MCL_ONFAULT = 0x4 + MEMERASE = 0x40084d02 + MEMERASE64 = 0x40104d14 + MEMGETBADBLOCK = 0x40084d0b + MEMGETINFO = 0x80204d01 + MEMGETOOBSEL = 0x80c84d0a + MEMGETREGIONCOUNT = 0x80044d07 + MEMISLOCKED = 0x80084d17 + MEMLOCK = 0x40084d05 + MEMREAD = 0xc0404d1a + MEMREADOOB = 0xc0104d04 + MEMSETBADBLOCK = 0x40084d0c + MEMUNLOCK = 0x40084d06 + MEMWRITEOOB = 0xc0104d03 + MTDFILEMODE = 0x4d13 + NFDBITS = 0x40 + NLDLY = 0x100 + NOFLSH = 0x80 + NS_GET_MNTNS_ID = 0x8008b705 + NS_GET_NSTYPE = 0xb703 + NS_GET_OWNER_UID = 0xb704 + NS_GET_PARENT = 0xb702 + NS_GET_PID_FROM_PIDNS = 0x8004b706 + NS_GET_PID_IN_PIDNS = 0x8004b708 + NS_GET_TGID_FROM_PIDNS = 0x8004b707 + NS_GET_TGID_IN_PIDNS = 0x8004b709 + NS_GET_USERNS = 0xb701 + OLCUC = 0x2 + ONLCR = 0x4 + OTPERASE = 0x400c4d19 + OTPGETREGIONCOUNT = 0x40044d0e + OTPGETREGIONINFO = 0x400c4d0f + OTPLOCK = 0x800c4d10 + OTPSELECT = 0x80044d0d + O_APPEND = 0x400 + O_ASYNC = 0x2000 + O_CLOEXEC = 0x80000 + O_CREAT = 0x40 + O_DIRECT = 0x4000 + O_DIRECTORY = 0x10000 + O_DSYNC = 0x1000 + O_EXCL = 0x80 + O_FSYNC = 0x101000 + O_LARGEFILE = 0x0 + O_NDELAY = 0x800 + O_NOATIME = 0x40000 + O_NOCTTY = 0x100 + O_NOFOLLOW = 0x20000 + O_NONBLOCK = 0x800 + O_PATH = 0x200000 + O_RSYNC = 0x101000 + O_SYNC = 0x101000 + O_TMPFILE = 0x410000 + O_TRUNC = 0x200 + PARENB = 0x100 + PARODD = 0x200 + PENDIN = 0x4000 + PERF_EVENT_IOC_DISABLE = 0x2401 + PERF_EVENT_IOC_ENABLE = 0x2400 + PERF_EVENT_IOC_ID = 0x80082407 + PERF_EVENT_IOC_MODIFY_ATTRIBUTES = 0x4008240b + PERF_EVENT_IOC_PAUSE_OUTPUT = 0x40042409 + PERF_EVENT_IOC_PERIOD = 0x40082404 + PERF_EVENT_IOC_QUERY_BPF = 0xc008240a + PERF_EVENT_IOC_REFRESH = 0x2402 + PERF_EVENT_IOC_RESET = 0x2403 + PERF_EVENT_IOC_SET_BPF = 0x40042408 + PERF_EVENT_IOC_SET_FILTER = 0x40082406 + PERF_EVENT_IOC_SET_OUTPUT = 0x2405 + PPPIOCATTACH = 0x4004743d + PPPIOCATTCHAN = 0x40047438 + PPPIOCBRIDGECHAN = 0x40047435 + PPPIOCCONNECT = 0x4004743a + PPPIOCDETACH = 0x4004743c + PPPIOCDISCONN = 0x7439 + PPPIOCGASYNCMAP = 0x80047458 + PPPIOCGCHAN = 0x80047437 + PPPIOCGDEBUG = 0x80047441 + PPPIOCGFLAGS = 0x8004745a + PPPIOCGIDLE = 0x8010743f + PPPIOCGIDLE32 = 0x8008743f + PPPIOCGIDLE64 = 0x8010743f + PPPIOCGL2TPSTATS = 0x80487436 + PPPIOCGMRU = 0x80047453 + PPPIOCGRASYNCMAP = 0x80047455 + PPPIOCGUNIT = 0x80047456 + PPPIOCGXASYNCMAP = 0x80207450 + PPPIOCSACTIVE = 0x40107446 + PPPIOCSASYNCMAP = 0x40047457 + PPPIOCSCOMPRESS = 0x4010744d + PPPIOCSDEBUG = 0x40047440 + PPPIOCSFLAGS = 0x40047459 + PPPIOCSMAXCID = 0x40047451 + PPPIOCSMRRU = 0x4004743b + PPPIOCSMRU = 0x40047452 + PPPIOCSNPMODE = 0x4008744b + PPPIOCSPASS = 0x40107447 + PPPIOCSRASYNCMAP = 0x40047454 + PPPIOCSXASYNCMAP = 0x4020744f + PPPIOCUNBRIDGECHAN = 0x7434 + PPPIOCXFERUNIT = 0x744e + PR_SET_PTRACER_ANY = 0xffffffffffffffff + PTP_CLOCK_GETCAPS = 0x80503d01 + PTP_CLOCK_GETCAPS2 = 0x80503d0a + PTP_ENABLE_PPS = 0x40043d04 + PTP_ENABLE_PPS2 = 0x40043d0d + PTP_EXTTS_REQUEST = 0x40103d02 + PTP_EXTTS_REQUEST2 = 0x40103d0b + PTP_MASK_CLEAR_ALL = 0x3d13 + PTP_MASK_EN_SINGLE = 0x40043d14 + PTP_PEROUT_REQUEST = 0x40383d03 + PTP_PEROUT_REQUEST2 = 0x40383d0c + PTP_PIN_SETFUNC = 0x40603d07 + PTP_PIN_SETFUNC2 = 0x40603d10 + PTP_SYS_OFFSET = 0x43403d05 + PTP_SYS_OFFSET2 = 0x43403d0e + PTRACE_GETFDPIC = 0x21 + PTRACE_GETFDPIC_EXEC = 0x0 + PTRACE_GETFDPIC_INTERP = 0x1 + RLIMIT_AS = 0x9 + RLIMIT_MEMLOCK = 0x8 + RLIMIT_NOFILE = 0x7 + RLIMIT_NPROC = 0x6 + RLIMIT_RSS = 0x5 + RNDADDENTROPY = 0x40085203 + RNDADDTOENTCNT = 0x40045201 + RNDCLEARPOOL = 0x5206 + RNDGETENTCNT = 0x80045200 + RNDGETPOOL = 0x80085202 + RNDRESEEDCRNG = 0x5207 + RNDZAPENTCNT = 0x5204 + RTC_AIE_OFF = 0x7002 + RTC_AIE_ON = 0x7001 + RTC_ALM_READ = 0x80247008 + RTC_ALM_SET = 0x40247007 + RTC_EPOCH_READ = 0x8008700d + RTC_EPOCH_SET = 0x4008700e + RTC_IRQP_READ = 0x8008700b + RTC_IRQP_SET = 0x4008700c + RTC_PARAM_GET = 0x40187013 + RTC_PARAM_SET = 0x40187014 + RTC_PIE_OFF = 0x7006 + RTC_PIE_ON = 0x7005 + RTC_PLL_GET = 0x80207011 + RTC_PLL_SET = 0x40207012 + RTC_RD_TIME = 0x80247009 + RTC_SET_TIME = 0x4024700a + RTC_UIE_OFF = 0x7004 + RTC_UIE_ON = 0x7003 + RTC_VL_CLR = 0x7014 + RTC_VL_READ = 0x80047013 + RTC_WIE_OFF = 0x7010 + RTC_WIE_ON = 0x700f + RTC_WKALM_RD = 0x80287010 + RTC_WKALM_SET = 0x4028700f + SCM_DEVMEM_DMABUF = 0x4f + SCM_DEVMEM_LINEAR = 0x4e + SCM_TIMESTAMPING = 0x25 + SCM_TIMESTAMPING_OPT_STATS = 0x36 + SCM_TIMESTAMPING_PKTINFO = 0x3a + SCM_TIMESTAMPNS = 0x23 + SCM_TS_OPT_ID = 0x51 + SCM_TXTIME = 0x3d + SCM_WIFI_STATUS = 0x29 + SECCOMP_IOCTL_NOTIF_ADDFD = 0x40182103 + SECCOMP_IOCTL_NOTIF_ID_VALID = 0x40082102 + SECCOMP_IOCTL_NOTIF_SET_FLAGS = 0x40082104 + SFD_CLOEXEC = 0x80000 + SFD_NONBLOCK = 0x800 + SIOCATMARK = 0x8905 + SIOCGPGRP = 0x8904 + SIOCGSTAMPNS_NEW = 0x80108907 + SIOCGSTAMP_NEW = 0x80108906 + SIOCINQ = 0x541b + SIOCOUTQ = 0x5411 + SIOCSPGRP = 0x8902 + SOCK_CLOEXEC = 0x80000 + SOCK_DGRAM = 0x2 + SOCK_NONBLOCK = 0x800 + SOCK_STREAM = 0x1 + SOL_SOCKET = 0x1 + SO_ACCEPTCONN = 0x1e + SO_ATTACH_BPF = 0x32 + SO_ATTACH_REUSEPORT_CBPF = 0x33 + SO_ATTACH_REUSEPORT_EBPF = 0x34 + SO_BINDTODEVICE = 0x19 + SO_BINDTOIFINDEX = 0x3e + SO_BPF_EXTENSIONS = 0x30 + SO_BROADCAST = 0x6 + SO_BSDCOMPAT = 0xe + SO_BUF_LOCK = 0x48 + SO_BUSY_POLL = 0x2e + SO_BUSY_POLL_BUDGET = 0x46 + SO_CNX_ADVICE = 0x35 + SO_COOKIE = 0x39 + SO_DETACH_REUSEPORT_BPF = 0x44 + SO_DEVMEM_DMABUF = 0x4f + SO_DEVMEM_DONTNEED = 0x50 + SO_DEVMEM_LINEAR = 0x4e + SO_DOMAIN = 0x27 + SO_DONTROUTE = 0x5 + SO_ERROR = 0x4 + SO_INCOMING_CPU = 0x31 + SO_INCOMING_NAPI_ID = 0x38 + SO_KEEPALIVE = 0x9 + SO_LINGER = 0xd + SO_LOCK_FILTER = 0x2c + SO_MARK = 0x24 + SO_MAX_PACING_RATE = 0x2f + SO_MEMINFO = 0x37 + SO_NETNS_COOKIE = 0x47 + SO_NOFCS = 0x2b + SO_OOBINLINE = 0xa + SO_PASSCRED = 0x10 + SO_PASSPIDFD = 0x4c + SO_PASSRIGHTS = 0x53 + SO_PASSSEC = 0x22 + SO_PEEK_OFF = 0x2a + SO_PEERCRED = 0x11 + SO_PEERGROUPS = 0x3b + SO_PEERPIDFD = 0x4d + SO_PEERSEC = 0x1f + SO_PREFER_BUSY_POLL = 0x45 + SO_PROTOCOL = 0x26 + SO_RCVBUF = 0x8 + SO_RCVBUFFORCE = 0x21 + SO_RCVLOWAT = 0x12 + SO_RCVMARK = 0x4b + SO_RCVPRIORITY = 0x52 + SO_RCVTIMEO = 0x14 + SO_RCVTIMEO_NEW = 0x42 + SO_RCVTIMEO_OLD = 0x14 + SO_RESERVE_MEM = 0x49 + SO_REUSEADDR = 0x2 + SO_REUSEPORT = 0xf + SO_RXQ_OVFL = 0x28 + SO_SECURITY_AUTHENTICATION = 0x16 + SO_SECURITY_ENCRYPTION_NETWORK = 0x18 + SO_SECURITY_ENCRYPTION_TRANSPORT = 0x17 + SO_SELECT_ERR_QUEUE = 0x2d + SO_SNDBUF = 0x7 + SO_SNDBUFFORCE = 0x20 + SO_SNDLOWAT = 0x13 + SO_SNDTIMEO = 0x15 + SO_SNDTIMEO_NEW = 0x43 + SO_SNDTIMEO_OLD = 0x15 + SO_TIMESTAMPING = 0x25 + SO_TIMESTAMPING_NEW = 0x41 + SO_TIMESTAMPING_OLD = 0x25 + SO_TIMESTAMPNS = 0x23 + SO_TIMESTAMPNS_NEW = 0x40 + SO_TIMESTAMPNS_OLD = 0x23 + SO_TIMESTAMP_NEW = 0x3f + SO_TXREHASH = 0x4a + SO_TXTIME = 0x3d + SO_TYPE = 0x3 + SO_WIFI_STATUS = 0x29 + SO_ZEROCOPY = 0x3c + TAB1 = 0x800 + TAB2 = 0x1000 + TAB3 = 0x1800 + TABDLY = 0x1800 + TCFLSH = 0x540b + TCGETA = 0x5405 + TCGETS = 0x5401 + TCGETS2 = 0x802c542a + TCGETX = 0x5432 + TCSAFLUSH = 0x2 + TCSBRK = 0x5409 + TCSBRKP = 0x5425 + TCSETA = 0x5406 + TCSETAF = 0x5408 + TCSETAW = 0x5407 + TCSETS = 0x5402 + TCSETS2 = 0x402c542b + TCSETSF = 0x5404 + TCSETSF2 = 0x402c542d + TCSETSW = 0x5403 + TCSETSW2 = 0x402c542c + TCSETX = 0x5433 + TCSETXF = 0x5434 + TCSETXW = 0x5435 + TCXONC = 0x540a + TFD_CLOEXEC = 0x80000 + TFD_NONBLOCK = 0x800 + TIOCCBRK = 0x5428 + TIOCCONS = 0x541d + TIOCEXCL = 0x540c + TIOCGDEV = 0x80045432 + TIOCGETD = 0x5424 + TIOCGEXCL = 0x80045440 + TIOCGICOUNT = 0x545d + TIOCGISO7816 = 0x80285442 + TIOCGLCKTRMIOS = 0x5456 + TIOCGPGRP = 0x540f + TIOCGPKT = 0x80045438 + TIOCGPTLCK = 0x80045439 + TIOCGPTN = 0x80045430 + TIOCGPTPEER = 0x5441 + TIOCGRS485 = 0x542e + TIOCGSERIAL = 0x541e + TIOCGSID = 0x5429 + TIOCGSOFTCAR = 0x5419 + TIOCGWINSZ = 0x5413 + TIOCINQ = 0x541b + TIOCLINUX = 0x541c + TIOCMBIC = 0x5417 + TIOCMBIS = 0x5416 + TIOCMGET = 0x5415 + TIOCMIWAIT = 0x545c + TIOCMSET = 0x5418 + TIOCM_CAR = 0x40 + TIOCM_CD = 0x40 + TIOCM_CTS = 0x20 + TIOCM_DSR = 0x100 + TIOCM_RI = 0x80 + TIOCM_RNG = 0x80 + TIOCM_SR = 0x10 + TIOCM_ST = 0x8 + TIOCNOTTY = 0x5422 + TIOCNXCL = 0x540d + TIOCOUTQ = 0x5411 + TIOCPKT = 0x5420 + TIOCSBRK = 0x5427 + TIOCSCTTY = 0x540e + TIOCSERCONFIG = 0x5453 + TIOCSERGETLSR = 0x5459 + TIOCSERGETMULTI = 0x545a + TIOCSERGSTRUCT = 0x5458 + TIOCSERGWILD = 0x5454 + TIOCSERSETMULTI = 0x545b + TIOCSERSWILD = 0x5455 + TIOCSER_TEMT = 0x1 + TIOCSETD = 0x5423 + TIOCSIG = 0x40045436 + TIOCSISO7816 = 0xc0285443 + TIOCSLCKTRMIOS = 0x5457 + TIOCSPGRP = 0x5410 + TIOCSPTLCK = 0x40045431 + TIOCSRS485 = 0x542f + TIOCSSERIAL = 0x541f + TIOCSSOFTCAR = 0x541a + TIOCSTI = 0x5412 + TIOCSWINSZ = 0x5414 + TIOCVHANGUP = 0x5437 + TOSTOP = 0x100 + TUNATTACHFILTER = 0x401054d5 + TUNDETACHFILTER = 0x401054d6 + TUNGETDEVNETNS = 0x54e3 + TUNGETFEATURES = 0x800454cf + TUNGETFILTER = 0x801054db + TUNGETIFF = 0x800454d2 + TUNGETSNDBUF = 0x800454d3 + TUNGETVNETBE = 0x800454df + TUNGETVNETHDRSZ = 0x800454d7 + TUNGETVNETLE = 0x800454dd + TUNSETCARRIER = 0x400454e2 + TUNSETDEBUG = 0x400454c9 + TUNSETFILTEREBPF = 0x800454e1 + TUNSETGROUP = 0x400454ce + TUNSETIFF = 0x400454ca + TUNSETIFINDEX = 0x400454da + TUNSETLINK = 0x400454cd + TUNSETNOCSUM = 0x400454c8 + TUNSETOFFLOAD = 0x400454d0 + TUNSETOWNER = 0x400454cc + TUNSETPERSIST = 0x400454cb + TUNSETQUEUE = 0x400454d9 + TUNSETSNDBUF = 0x400454d4 + TUNSETSTEERINGEBPF = 0x800454e0 + TUNSETTXFILTER = 0x400454d1 + TUNSETVNETBE = 0x400454de + TUNSETVNETHDRSZ = 0x400454d8 + TUNSETVNETLE = 0x400454dc + UBI_IOCATT = 0x40186f40 + UBI_IOCDET = 0x40046f41 + UBI_IOCEBCH = 0x40044f02 + UBI_IOCEBER = 0x40044f01 + UBI_IOCEBISMAP = 0x80044f05 + UBI_IOCEBMAP = 0x40084f03 + UBI_IOCEBUNMAP = 0x40044f04 + UBI_IOCMKVOL = 0x40986f00 + UBI_IOCRMVOL = 0x40046f01 + UBI_IOCRNVOL = 0x51106f03 + UBI_IOCRPEB = 0x40046f04 + UBI_IOCRSVOL = 0x400c6f02 + UBI_IOCSETVOLPROP = 0x40104f06 + UBI_IOCSPEB = 0x40046f05 + UBI_IOCVOLCRBLK = 0x40804f07 + UBI_IOCVOLRMBLK = 0x4f08 + UBI_IOCVOLUP = 0x40084f00 + VDISCARD = 0xd + VEOF = 0x4 + VEOL = 0xb + VEOL2 = 0x10 + VMIN = 0x6 + VREPRINT = 0xc + VSTART = 0x8 + VSTOP = 0x9 + VSUSP = 0xa + VSWTC = 0x7 + VT1 = 0x4000 + VTDLY = 0x4000 + VTIME = 0x5 + VWERASE = 0xe + WDIOC_GETBOOTSTATUS = 0x80045702 + WDIOC_GETPRETIMEOUT = 0x80045709 + WDIOC_GETSTATUS = 0x80045701 + WDIOC_GETSUPPORT = 0x80285700 + WDIOC_GETTEMP = 0x80045703 + WDIOC_GETTIMELEFT = 0x8004570a + WDIOC_GETTIMEOUT = 0x80045707 + WDIOC_KEEPALIVE = 0x80045705 + WDIOC_SETOPTIONS = 0x80045704 + WORDSIZE = 0x40 + XCASE = 0x4 + XTABS = 0x1800 + _HIDIOCGRAWNAME = 0x80804804 + _HIDIOCGRAWPHYS = 0x80404805 + _HIDIOCGRAWUNIQ = 0x80404808 ) // Errors @@ -601,8 +585,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -826,7 +808,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 6e87bd659..64347eb35 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -156,7 +156,6 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x8008b70d NS_GET_MNTNS_ID = 0x8008b705 NS_GET_NSTYPE = 0xb703 NS_GET_OWNER_UID = 0xb704 @@ -368,7 +367,6 @@ const ( RTC_WKALM_SET = 0x4028700f SCM_DEVMEM_DMABUF = 0x4f SCM_DEVMEM_LINEAR = 0x4e - SCM_INQ = 0x54 SCM_TIMESTAMPING = 0x25 SCM_TIMESTAMPING_OPT_STATS = 0x36 SCM_TIMESTAMPING_PKTINFO = 0x3a @@ -416,7 +414,6 @@ const ( SO_ERROR = 0x4 SO_INCOMING_CPU = 0x31 SO_INCOMING_NAPI_ID = 0x38 - SO_INQ = 0x54 SO_KEEPALIVE = 0x9 SO_LINGER = 0xd SO_LOCK_FILTER = 0x2c @@ -660,8 +657,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x59) EDOTDOT = syscall.Errno(0x49) EDQUOT = syscall.Errno(0x7a) - EFSBADCRC = syscall.Errno(0x4a) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x70) EHOSTUNREACH = syscall.Errno(0x71) EHWPOISON = syscall.Errno(0x85) @@ -885,7 +880,7 @@ var errorList = [...]struct { {114, "EALREADY", "operation already in progress"}, {115, "EINPROGRESS", "operation now in progress"}, {116, "ESTALE", "stale file handle"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 7e2b2e8a6..7d7191171 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -161,7 +161,6 @@ const ( NFDBITS = 0x40 NLDLY = 0x100 NOFLSH = 0x80 - NS_GET_ID = 0x4008b70d NS_GET_MNTNS_ID = 0x4008b705 NS_GET_NSTYPE = 0x2000b703 NS_GET_OWNER_UID = 0x2000b704 @@ -359,7 +358,6 @@ const ( RTC_WKALM_SET = 0x8028700f SCM_DEVMEM_DMABUF = 0x58 SCM_DEVMEM_LINEAR = 0x57 - SCM_INQ = 0x5d SCM_TIMESTAMPING = 0x23 SCM_TIMESTAMPING_OPT_STATS = 0x38 SCM_TIMESTAMPING_PKTINFO = 0x3c @@ -455,7 +453,6 @@ const ( SO_ERROR = 0x1007 SO_INCOMING_CPU = 0x33 SO_INCOMING_NAPI_ID = 0x3a - SO_INQ = 0x5d SO_KEEPALIVE = 0x8 SO_LINGER = 0x80 SO_LOCK_FILTER = 0x28 @@ -697,8 +694,6 @@ const ( EDESTADDRREQ = syscall.Errno(0x27) EDOTDOT = syscall.Errno(0x58) EDQUOT = syscall.Errno(0x45) - EFSBADCRC = syscall.Errno(0x4c) - EFSCORRUPTED = syscall.Errno(0x75) EHOSTDOWN = syscall.Errno(0x40) EHOSTUNREACH = syscall.Errno(0x41) EHWPOISON = syscall.Errno(0x87) @@ -926,7 +921,7 @@ var errorList = [...]struct { {114, "ELIBACC", "can not access a needed shared library"}, {115, "ENOTUNIQ", "name not unique on network"}, {116, "ERESTART", "interrupted system call should be restarted"}, - {117, "EFSCORRUPTED", "structure needs cleaning"}, + {117, "EUCLEAN", "structure needs cleaning"}, {118, "ENOTNAM", "not a XENIX named type file"}, {119, "ENAVAIL", "no XENIX semaphores available"}, {120, "EISNAM", "is a named type file"}, diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 80f40e401..886f5de5b 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -1785,7 +1785,7 @@ func writev(fd int, iovs []Iovec) (n int, err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func preadvSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) { +func preadv(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) { var _p0 unsafe.Pointer if len(iovs) > 0 { _p0 = unsafe.Pointer(&iovs[0]) @@ -1802,7 +1802,7 @@ func preadvSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pwritevSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) { +func pwritev(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int, err error) { var _p0 unsafe.Pointer if len(iovs) > 0 { _p0 = unsafe.Pointer(&iovs[0]) @@ -1819,7 +1819,7 @@ func pwritevSyscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr) (n int // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func preadv2Syscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) { +func preadv2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) { var _p0 unsafe.Pointer if len(iovs) > 0 { _p0 = unsafe.Pointer(&iovs[0]) @@ -1836,7 +1836,7 @@ func preadv2Syscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func pwritev2Syscall(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) { +func pwritev2(fd int, iovs []Iovec, offs_l uintptr, offs_h uintptr, flags int) (n int, err error) { var _p0 unsafe.Pointer if len(iovs) > 0 { _p0 = unsafe.Pointer(&iovs[0]) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go index 6487475f0..1851df14e 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.go @@ -1633,90 +1633,6 @@ var libc_pwrite_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readv(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_readv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_readv readv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writev(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_writev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_writev writev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_preadv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_preadv preadv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), uintptr(offset>>32), 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_pwritev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_pwritev pwritev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func read(fd int, p []byte) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s index f10201dac..0b43c6936 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_386.s @@ -498,26 +498,6 @@ TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $4 DATA ·libc_pwrite_trampoline_addr(SB)/4, $libc_pwrite_trampoline<>(SB) -TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_readv(SB) -GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $4 -DATA ·libc_readv_trampoline_addr(SB)/4, $libc_readv_trampoline<>(SB) - -TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_writev(SB) -GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $4 -DATA ·libc_writev_trampoline_addr(SB)/4, $libc_writev_trampoline<>(SB) - -TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_preadv(SB) -GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $4 -DATA ·libc_preadv_trampoline_addr(SB)/4, $libc_preadv_trampoline<>(SB) - -TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_pwritev(SB) -GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $4 -DATA ·libc_pwritev_trampoline_addr(SB)/4, $libc_pwritev_trampoline<>(SB) - TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_read(SB) GLOBL ·libc_read_trampoline_addr(SB), RODATA, $4 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go index 50980475d..e1ec0dbe4 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.go @@ -1633,90 +1633,6 @@ var libc_pwrite_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readv(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_readv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_readv readv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writev(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_writev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_writev writev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_preadv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_preadv preadv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_pwritev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_pwritev pwritev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func read(fd int, p []byte) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s index 9de2cbaa4..880c6d6e3 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_amd64.s @@ -498,26 +498,6 @@ TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) -TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_readv(SB) -GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) - -TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_writev(SB) -GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) - -TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_preadv(SB) -GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) - -TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_pwritev(SB) -GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) - TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_read(SB) GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go index 33c9c3a43..7c8452a63 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.go @@ -1633,90 +1633,6 @@ var libc_pwrite_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readv(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_readv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_readv readv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writev(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_writev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_writev writev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), 0, uintptr(offset), uintptr(offset>>32)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_preadv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_preadv preadv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), 0, uintptr(offset), uintptr(offset>>32)) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_pwritev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_pwritev pwritev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func read(fd int, p []byte) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s index c6b9175a6..b8ef95b0f 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm.s @@ -498,26 +498,6 @@ TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $4 DATA ·libc_pwrite_trampoline_addr(SB)/4, $libc_pwrite_trampoline<>(SB) -TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_readv(SB) -GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $4 -DATA ·libc_readv_trampoline_addr(SB)/4, $libc_readv_trampoline<>(SB) - -TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_writev(SB) -GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $4 -DATA ·libc_writev_trampoline_addr(SB)/4, $libc_writev_trampoline<>(SB) - -TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_preadv(SB) -GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $4 -DATA ·libc_preadv_trampoline_addr(SB)/4, $libc_preadv_trampoline<>(SB) - -TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_pwritev(SB) -GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $4 -DATA ·libc_pwritev_trampoline_addr(SB)/4, $libc_pwritev_trampoline<>(SB) - TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_read(SB) GLOBL ·libc_read_trampoline_addr(SB), RODATA, $4 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go index d3410262e..2ffdf861f 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.go @@ -1633,90 +1633,6 @@ var libc_pwrite_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readv(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_readv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_readv readv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writev(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_writev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_writev writev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_preadv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_preadv preadv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_pwritev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_pwritev pwritev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func read(fd int, p []byte) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s index 1be10bb45..2af3b5c76 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_arm64.s @@ -498,26 +498,6 @@ TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) -TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_readv(SB) -GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) - -TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_writev(SB) -GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) - -TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_preadv(SB) -GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) - -TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_pwritev(SB) -GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) - TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_read(SB) GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go index dea19d54e..1da08d526 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.go @@ -1633,90 +1633,6 @@ var libc_pwrite_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readv(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_readv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_readv readv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writev(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_writev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_writev writev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_preadv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_preadv preadv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_pwritev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_pwritev pwritev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func read(fd int, p []byte) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s index a9fec24d9..b7a251353 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_mips64.s @@ -498,26 +498,6 @@ TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) -TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_readv(SB) -GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) - -TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_writev(SB) -GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) - -TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_preadv(SB) -GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) - -TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_pwritev(SB) -GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) - TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_read(SB) GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go index 436efb586..6e85b0aac 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.go @@ -1633,90 +1633,6 @@ var libc_pwrite_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readv(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_readv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_readv readv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writev(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_writev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_writev writev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_preadv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_preadv preadv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_pwritev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_pwritev pwritev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func read(fd int, p []byte) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s index 441ed4e40..f15dadf05 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_ppc64.s @@ -597,30 +597,6 @@ TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) -TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 - CALL libc_readv(SB) - RET -GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) - -TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 - CALL libc_writev(SB) - RET -GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) - -TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 - CALL libc_preadv(SB) - RET -GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) - -TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 - CALL libc_pwritev(SB) - RET -GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) - TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 CALL libc_read(SB) RET diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go index d801e4b4e..28b487df2 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.go @@ -1633,90 +1633,6 @@ var libc_pwrite_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT -func readv(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_readv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_readv readv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func writev(fd int, iovecs []Iovec) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_writev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_writev writev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_preadv_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_preadv preadv "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - -func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { - var _p0 unsafe.Pointer - if len(iovecs) > 0 { - _p0 = unsafe.Pointer(&iovecs[0]) - } else { - _p0 = unsafe.Pointer(&_zero) - } - r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) - n = int(r0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} - -var libc_pwritev_trampoline_addr uintptr - -//go:cgo_import_dynamic libc_pwritev pwritev "libc.so" - -// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT - func read(fd int, p []byte) (n int, err error) { var _p0 unsafe.Pointer if len(p) > 0 { diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s index b15cc0174..1e7f321e4 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsyscall_openbsd_riscv64.s @@ -498,26 +498,6 @@ TEXT libc_pwrite_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_pwrite_trampoline_addr(SB), RODATA, $8 DATA ·libc_pwrite_trampoline_addr(SB)/8, $libc_pwrite_trampoline<>(SB) -TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_readv(SB) -GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) - -TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_writev(SB) -GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) - -TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_preadv(SB) -GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 -DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) - -TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 - JMP libc_pwritev(SB) -GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 -DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) - TEXT libc_read_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_read(SB) GLOBL ·libc_read_trampoline_addr(SB), RODATA, $8 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go index 49d1b8803..aca56ee49 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_386.go @@ -463,8 +463,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go index f11f1de77..2ea1ef58c 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_amd64.go @@ -342,7 +342,6 @@ const ( SYS_IO_PGETEVENTS = 333 SYS_RSEQ = 334 SYS_URETPROBE = 335 - SYS_UPROBE = 336 SYS_PIDFD_SEND_SIGNAL = 424 SYS_IO_URING_SETUP = 425 SYS_IO_URING_ENTER = 426 @@ -387,8 +386,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go index bad740b79..d22c8af31 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_arm.go @@ -427,8 +427,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go index fe646d18e..5ee264ae9 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_arm64.go @@ -330,8 +330,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go index 4362f6d55..f9f03ebf5 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_loong64.go @@ -306,7 +306,6 @@ const ( SYS_LANDLOCK_CREATE_RULESET = 444 SYS_LANDLOCK_ADD_RULE = 445 SYS_LANDLOCK_RESTRICT_SELF = 446 - SYS_MEMFD_SECRET = 447 SYS_PROCESS_MRELEASE = 448 SYS_FUTEX_WAITV = 449 SYS_SET_MEMPOLICY_HOME_NODE = 450 @@ -327,8 +326,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go index b63d155ae..87c2118e8 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips.go @@ -447,8 +447,4 @@ const ( SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 SYS_OPEN_TREE_ATTR = 4467 - SYS_FILE_GETATTR = 4468 - SYS_FILE_SETATTR = 4469 - SYS_LISTNS = 4470 - SYS_RSEQ_SLICE_YIELD = 4471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go index 435d43319..391ad102f 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64.go @@ -377,8 +377,4 @@ const ( SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 SYS_OPEN_TREE_ATTR = 5467 - SYS_FILE_GETATTR = 5468 - SYS_FILE_SETATTR = 5469 - SYS_LISTNS = 5470 - SYS_RSEQ_SLICE_YIELD = 5471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go index dcc0468d6..565615775 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mips64le.go @@ -377,8 +377,4 @@ const ( SYS_LISTXATTRAT = 5465 SYS_REMOVEXATTRAT = 5466 SYS_OPEN_TREE_ATTR = 5467 - SYS_FILE_GETATTR = 5468 - SYS_FILE_SETATTR = 5469 - SYS_LISTNS = 5470 - SYS_RSEQ_SLICE_YIELD = 5471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go index b96f85ebd..0482b52e3 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_mipsle.go @@ -447,8 +447,4 @@ const ( SYS_LISTXATTRAT = 4465 SYS_REMOVEXATTRAT = 4466 SYS_OPEN_TREE_ATTR = 4467 - SYS_FILE_GETATTR = 4468 - SYS_FILE_SETATTR = 4469 - SYS_LISTNS = 4470 - SYS_RSEQ_SLICE_YIELD = 4471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go index bffa2bd1e..71806f08f 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc.go @@ -454,8 +454,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go index 57bfc6b26..e35a71058 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64.go @@ -426,8 +426,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go index 750f706d5..2aea47670 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_ppc64le.go @@ -426,8 +426,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go index 303ccbf46..6c9bb4e56 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_riscv64.go @@ -331,8 +331,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go index 5e5dd4ccb..680bc9915 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go @@ -392,8 +392,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go index f7c4fb3df..620f27105 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/zsysnum_linux_sparc64.go @@ -374,7 +374,6 @@ const ( SYS_FSMOUNT = 432 SYS_FSPICK = 433 SYS_PIDFD_OPEN = 434 - SYS_CLONE3 = 435 SYS_CLOSE_RANGE = 436 SYS_OPENAT2 = 437 SYS_PIDFD_GETFD = 438 @@ -406,8 +405,4 @@ const ( SYS_LISTXATTRAT = 465 SYS_REMOVEXATTRAT = 466 SYS_OPEN_TREE_ATTR = 467 - SYS_FILE_GETATTR = 468 - SYS_FILE_SETATTR = 469 - SYS_LISTNS = 470 - SYS_RSEQ_SLICE_YIELD = 471 ) diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux.go index d11d5b96a..45476a73c 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -18,11 +18,6 @@ type ( _C_long_long int64 ) -type KernelTimespec struct { - Sec int64 - Nsec int64 -} - type ItimerSpec struct { Interval Timespec Value Timespec @@ -526,14 +521,6 @@ type TCPInfo struct { Total_rto uint16 Total_rto_recoveries uint16 Total_rto_time uint32 - Received_ce uint32 - Delivered_e1_bytes uint32 - Delivered_e0_bytes uint32 - Delivered_ce_bytes uint32 - Received_e1_bytes uint32 - Received_e0_bytes uint32 - Received_ce_bytes uint32 - _ [4]byte } type TCPVegasInfo struct { @@ -599,7 +586,7 @@ const ( SizeofIPv6MTUInfo = 0x20 SizeofICMPv6Filter = 0x20 SizeofUcred = 0xc - SizeofTCPInfo = 0x118 + SizeofTCPInfo = 0xf8 SizeofTCPCCInfo = 0x14 SizeofCanFilter = 0x8 SizeofTCPRepairOpt = 0x8 @@ -1337,7 +1324,7 @@ const ( PERF_RECORD_CGROUP = 0x13 PERF_RECORD_TEXT_POKE = 0x14 PERF_RECORD_AUX_OUTPUT_HW_ID = 0x15 - PERF_RECORD_MAX = 0x17 + PERF_RECORD_MAX = 0x16 PERF_RECORD_KSYMBOL_TYPE_UNKNOWN = 0x0 PERF_RECORD_KSYMBOL_TYPE_BPF = 0x1 PERF_RECORD_KSYMBOL_TYPE_OOL = 0x2 @@ -3579,7 +3566,7 @@ const ( DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES = 0xae DEVLINK_ATTR_NESTED_DEVLINK = 0xaf DEVLINK_ATTR_SELFTESTS = 0xb0 - DEVLINK_ATTR_MAX = 0xb7 + DEVLINK_ATTR_MAX = 0xb3 DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE = 0x0 DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX = 0x1 DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT = 0x0 @@ -3901,7 +3888,7 @@ const ( ETHTOOL_MSG_PHY_GET = 0x2d ETHTOOL_MSG_TSCONFIG_GET = 0x2e ETHTOOL_MSG_TSCONFIG_SET = 0x2f - ETHTOOL_MSG_USER_MAX = 0x33 + ETHTOOL_MSG_USER_MAX = 0x2f ETHTOOL_MSG_KERNEL_NONE = 0x0 ETHTOOL_MSG_STRSET_GET_REPLY = 0x1 ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2 @@ -3951,7 +3938,7 @@ const ( ETHTOOL_MSG_PHY_NTF = 0x2e ETHTOOL_MSG_TSCONFIG_GET_REPLY = 0x2f ETHTOOL_MSG_TSCONFIG_SET_REPLY = 0x30 - ETHTOOL_MSG_KERNEL_MAX = 0x36 + ETHTOOL_MSG_KERNEL_MAX = 0x30 ETHTOOL_FLAG_COMPACT_BITSETS = 0x1 ETHTOOL_FLAG_OMIT_REPLY = 0x2 ETHTOOL_FLAG_STATS = 0x4 @@ -4880,7 +4867,7 @@ const ( NL80211_ATTR_MAC_HINT = 0xc8 NL80211_ATTR_MAC_MASK = 0xd7 NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca - NL80211_ATTR_MAX = 0x15c + NL80211_ATTR_MAX = 0x151 NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4 NL80211_ATTR_MAX_CSA_COUNTERS = 0xce NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS = 0x143 @@ -5095,12 +5082,12 @@ const ( NL80211_ATTR_WOWLAN_TRIGGERS = 0x75 NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED = 0x76 NL80211_ATTR_WPA_VERSIONS = 0x4b - NL80211_AUTHTYPE_AUTOMATIC = 0x9 + NL80211_AUTHTYPE_AUTOMATIC = 0x8 NL80211_AUTHTYPE_FILS_PK = 0x7 NL80211_AUTHTYPE_FILS_SK = 0x5 NL80211_AUTHTYPE_FILS_SK_PFS = 0x6 NL80211_AUTHTYPE_FT = 0x2 - NL80211_AUTHTYPE_MAX = 0x8 + NL80211_AUTHTYPE_MAX = 0x7 NL80211_AUTHTYPE_NETWORK_EAP = 0x3 NL80211_AUTHTYPE_OPEN_SYSTEM = 0x0 NL80211_AUTHTYPE_SAE = 0x4 @@ -5133,7 +5120,7 @@ const ( NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY = 0x3 NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE = 0x5 NL80211_BAND_IFTYPE_ATTR_IFTYPES = 0x1 - NL80211_BAND_IFTYPE_ATTR_MAX = 0xd + NL80211_BAND_IFTYPE_ATTR_MAX = 0xb NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS = 0x7 NL80211_BAND_LC = 0x5 NL80211_BAND_S1GHZ = 0x4 @@ -5268,7 +5255,7 @@ const ( NL80211_CMD_LEAVE_MESH = 0x45 NL80211_CMD_LEAVE_OCB = 0x6d NL80211_CMD_LINKS_REMOVED = 0x9a - NL80211_CMD_MAX = 0x9f + NL80211_CMD_MAX = 0x9d NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29 NL80211_CMD_MODIFY_LINK_STA = 0x97 NL80211_CMD_NAN_MATCH = 0x78 @@ -5514,7 +5501,7 @@ const ( NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf - NL80211_FREQUENCY_ATTR_MAX = 0x27 + NL80211_FREQUENCY_ATTR_MAX = 0x22 NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6 NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11 NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc @@ -5779,7 +5766,7 @@ const ( NL80211_PMSR_FTM_CAPA_ATTR_ASAP = 0x1 NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS = 0x6 NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT = 0x7 - NL80211_PMSR_FTM_CAPA_ATTR_MAX = 0x12 + NL80211_PMSR_FTM_CAPA_ATTR_MAX = 0xa NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST = 0x8 NL80211_PMSR_FTM_CAPA_ATTR_NON_ASAP = 0x2 NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED = 0xa @@ -5801,7 +5788,7 @@ const ( NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD = 0x4 NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST = 0x6 NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK = 0xc - NL80211_PMSR_FTM_REQ_ATTR_MAX = 0xe + NL80211_PMSR_FTM_REQ_ATTR_MAX = 0xd NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED = 0xb NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP = 0x3 NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES = 0x7 @@ -5819,7 +5806,7 @@ const ( NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON = 0x1 NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST = 0x8 NL80211_PMSR_FTM_RESP_ATTR_LCI = 0x13 - NL80211_PMSR_FTM_RESP_ATTR_MAX = 0x16 + NL80211_PMSR_FTM_RESP_ATTR_MAX = 0x15 NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP = 0x6 NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS = 0x3 NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES = 0x4 @@ -5926,7 +5913,7 @@ const ( NL80211_RATE_INFO_HE_RU_ALLOC_52 = 0x1 NL80211_RATE_INFO_HE_RU_ALLOC_996 = 0x5 NL80211_RATE_INFO_HE_RU_ALLOC = 0x11 - NL80211_RATE_INFO_MAX = 0x20 + NL80211_RATE_INFO_MAX = 0x1d NL80211_RATE_INFO_MCS = 0x2 NL80211_RATE_INFO_S1G_MCS = 0x17 NL80211_RATE_INFO_S1G_NSS = 0x18 @@ -6180,7 +6167,7 @@ const ( NL80211_TXRATE_HT = 0x2 NL80211_TXRATE_LEGACY = 0x1 NL80211_TX_RATE_LIMITED = 0x1 - NL80211_TXRATE_MAX = 0xa + NL80211_TXRATE_MAX = 0x7 NL80211_TXRATE_MCS = 0x2 NL80211_TXRATE_VHT = 0x3 NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT = 0x1 @@ -6196,7 +6183,7 @@ const ( NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE = 0x2 NL80211_WIPHY_RADIO_ATTR_INDEX = 0x1 NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION = 0x3 - NL80211_WIPHY_RADIO_ATTR_MAX = 0x5 + NL80211_WIPHY_RADIO_ATTR_MAX = 0x4 NL80211_WIPHY_RADIO_FREQ_ATTR_END = 0x2 NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = 0x2 NL80211_WIPHY_RADIO_FREQ_ATTR_START = 0x1 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 97ef790de..485f2d3a1 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -354,14 +354,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint32 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 90b50da68..ecbd1ad8b 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -367,14 +367,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index acda13685..02f0463a4 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -345,14 +345,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint32 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index ef7a99e1f..6f4d400d2 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -346,14 +346,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 966063dfc..cd532cfa5 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -347,14 +347,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index dc53b20b7..413362085 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -350,14 +350,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint32 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 9ad0aa8c3..eaa37eb71 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -349,14 +349,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index 29d55493d..98ae6a1e4 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -349,14 +349,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index a4d9e1584..cae196159 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -350,14 +350,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint32 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index f8a297771..6ce3b4e02 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -357,14 +357,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint32 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 4158d6c4e..c7429c6a1 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -356,14 +356,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 1035af49f..4bf4baf4c 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -356,14 +356,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index 2297125d3..e9709d70a 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -374,14 +374,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 8481e9bd9..fb44268ca 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -369,14 +369,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index a6828a031..9c38265c7 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -351,14 +351,6 @@ type Taskstats struct { Wpcopy_delay_min uint64 Irq_delay_max uint64 Irq_delay_min uint64 - Cpu_delay_max_ts KernelTimespec - Blkio_delay_max_ts KernelTimespec - Swapin_delay_max_ts KernelTimespec - Freepages_delay_max_ts KernelTimespec - Thrashing_delay_max_ts KernelTimespec - Compact_delay_max_ts KernelTimespec - Wpcopy_delay_max_ts KernelTimespec - Irq_delay_max_ts KernelTimespec } type cpuMask uint64 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/syscall_windows.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/syscall_windows.go index 9755bca9f..453a7b97f 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -452,7 +452,6 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys RtlInitString(destinationString *NTString, sourceString *byte) = ntdll.RtlInitString //sys NtCreateFile(handle *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, allocationSize *int64, attributes uint32, share uint32, disposition uint32, options uint32, eabuffer uintptr, ealength uint32) (ntstatus error) = ntdll.NtCreateFile //sys NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, iosb *IO_STATUS_BLOCK, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (ntstatus error) = ntdll.NtCreateNamedPipeFile -//sys NtQueryInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, outBuffer *byte, outBufferLen uint32, class uint32) (ntstatus error) = ntdll.NtQueryInformationFile //sys NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) = ntdll.NtSetInformationFile //sys RtlDosPathNameToNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToNtPathName_U_WithStatus //sys RtlDosPathNameToRelativeNtPathName(dosName *uint16, ntName *NTUnicodeString, ntFileNamePart *uint16, relativeName *RTL_RELATIVE_NAME) (ntstatus error) = ntdll.RtlDosPathNameToRelativeNtPathName_U_WithStatus @@ -461,8 +460,6 @@ func NewCallbackCDecl(fn interface{}) uintptr { //sys NtSetInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32) (ntstatus error) = ntdll.NtSetInformationProcess //sys NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32, retLen *uint32) (ntstatus error) = ntdll.NtQuerySystemInformation //sys NtSetSystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInfoLen uint32) (ntstatus error) = ntdll.NtSetSystemInformation -//sys NtQueryEaFile(handle Handle, iosb *IO_STATUS_BLOCK, outBuffer *byte, outBufferLen uint32, returnSingleEntry bool, eaList *byte, eaListLen uint32, eaIndex *uint32, restartScan bool) (ntstatus error) = ntdll.NtQueryEaFile -//sys NtSetEaFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32) (ntstatus error) = ntdll.NtSetEaFile //sys RtlAddFunctionTable(functionTable *RUNTIME_FUNCTION, entryCount uint32, baseAddress uintptr) (ret bool) = ntdll.RtlAddFunctionTable //sys RtlDeleteFunctionTable(functionTable *RUNTIME_FUNCTION) (ret bool) = ntdll.RtlDeleteFunctionTable diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/types_windows.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/types_windows.go index d2574a73e..d82299e33 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/types_windows.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/types_windows.go @@ -3043,10 +3043,8 @@ const ( ) const ( - // FileInformationClass for NtSetInformationFile/NtQueryInformationFile, see - // https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ne-wdm-_file_information_class + // FileInformationClass for NtSetInformationFile FileBasicInformation = 4 - FileEaInformation = 7 FileRenameInformation = 10 FileDispositionInformation = 13 FilePositionInformation = 14 diff --git a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 192d19300..a506ac0f1 100644 --- a/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/src/code.cloudfoundry.org/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -428,11 +428,8 @@ var ( procNetUserGetInfo = modnetapi32.NewProc("NetUserGetInfo") procNtCreateFile = modntdll.NewProc("NtCreateFile") procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile") - procNtQueryEaFile = modntdll.NewProc("NtQueryEaFile") - procNtQueryInformationFile = modntdll.NewProc("NtQueryInformationFile") procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess") procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation") - procNtSetEaFile = modntdll.NewProc("NtSetEaFile") procNtSetInformationFile = modntdll.NewProc("NtSetInformationFile") procNtSetInformationProcess = modntdll.NewProc("NtSetInformationProcess") procNtSetSystemInformation = modntdll.NewProc("NtSetSystemInformation") @@ -3743,30 +3740,6 @@ func NtCreateNamedPipeFile(pipe *Handle, access uint32, oa *OBJECT_ATTRIBUTES, i return } -func NtQueryEaFile(handle Handle, iosb *IO_STATUS_BLOCK, outBuffer *byte, outBufferLen uint32, returnSingleEntry bool, eaList *byte, eaListLen uint32, eaIndex *uint32, restartScan bool) (ntstatus error) { - var _p0 uint32 - if returnSingleEntry { - _p0 = 1 - } - var _p1 uint32 - if restartScan { - _p1 = 1 - } - r0, _, _ := syscall.SyscallN(procNtQueryEaFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferLen), uintptr(_p0), uintptr(unsafe.Pointer(eaList)), uintptr(eaListLen), uintptr(unsafe.Pointer(eaIndex)), uintptr(_p1)) - if r0 != 0 { - ntstatus = NTStatus(r0) - } - return -} - -func NtQueryInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, outBuffer *byte, outBufferLen uint32, class uint32) (ntstatus error) { - r0, _, _ := syscall.SyscallN(procNtQueryInformationFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(outBuffer)), uintptr(outBufferLen), uintptr(class)) - if r0 != 0 { - ntstatus = NTStatus(r0) - } - return -} - func NtQueryInformationProcess(proc Handle, procInfoClass int32, procInfo unsafe.Pointer, procInfoLen uint32, retLen *uint32) (ntstatus error) { r0, _, _ := syscall.SyscallN(procNtQueryInformationProcess.Addr(), uintptr(proc), uintptr(procInfoClass), uintptr(procInfo), uintptr(procInfoLen), uintptr(unsafe.Pointer(retLen))) if r0 != 0 { @@ -3783,14 +3756,6 @@ func NtQuerySystemInformation(sysInfoClass int32, sysInfo unsafe.Pointer, sysInf return } -func NtSetEaFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32) (ntstatus error) { - r0, _, _ := syscall.SyscallN(procNtSetEaFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen)) - if r0 != 0 { - ntstatus = NTStatus(r0) - } - return -} - func NtSetInformationFile(handle Handle, iosb *IO_STATUS_BLOCK, inBuffer *byte, inBufferLen uint32, class uint32) (ntstatus error) { r0, _, _ := syscall.SyscallN(procNtSetInformationFile.Addr(), uintptr(handle), uintptr(unsafe.Pointer(iosb)), uintptr(unsafe.Pointer(inBuffer)), uintptr(inBufferLen), uintptr(class)) if r0 != 0 { diff --git a/src/code.cloudfoundry.org/vendor/google.golang.org/grpc/version.go b/src/code.cloudfoundry.org/vendor/google.golang.org/grpc/version.go index 3ccfe515f..7ac723c12 100644 --- a/src/code.cloudfoundry.org/vendor/google.golang.org/grpc/version.go +++ b/src/code.cloudfoundry.org/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.81.1" +const Version = "1.81.0" diff --git a/src/code.cloudfoundry.org/vendor/modules.txt b/src/code.cloudfoundry.org/vendor/modules.txt index 198214b67..2b5261b37 100644 --- a/src/code.cloudfoundry.org/vendor/modules.txt +++ b/src/code.cloudfoundry.org/vendor/modules.txt @@ -3,27 +3,27 @@ code.cloudfoundry.org/bbs/db/sqldb/helpers code.cloudfoundry.org/bbs/db/sqldb/helpers/monitor code.cloudfoundry.org/bbs/guidprovider -# code.cloudfoundry.org/cfhttp/v2 v2.78.0 +# code.cloudfoundry.org/cfhttp/v2 v2.76.0 ## explicit; go 1.25.0 code.cloudfoundry.org/cfhttp/v2 -# code.cloudfoundry.org/clock v1.71.0 +# code.cloudfoundry.org/clock v1.69.0 ## explicit; go 1.25.0 code.cloudfoundry.org/clock code.cloudfoundry.org/clock/fakeclock -# code.cloudfoundry.org/debugserver v0.97.0 +# code.cloudfoundry.org/debugserver v0.95.0 ## explicit; go 1.25.0 code.cloudfoundry.org/debugserver -# code.cloudfoundry.org/diego-logging-client v0.106.0 -## explicit; go 1.25.1 +# code.cloudfoundry.org/diego-logging-client v0.104.0 +## explicit; go 1.25.0 code.cloudfoundry.org/diego-logging-client code.cloudfoundry.org/diego-logging-client/testhelpers -# code.cloudfoundry.org/durationjson v0.73.0 +# code.cloudfoundry.org/durationjson v0.71.0 ## explicit; go 1.25.0 code.cloudfoundry.org/durationjson -# code.cloudfoundry.org/eventhub v0.73.0 +# code.cloudfoundry.org/eventhub v0.71.0 ## explicit; go 1.25.0 code.cloudfoundry.org/eventhub -# code.cloudfoundry.org/go-diodes v0.0.0-20260518082450-53acbbed6d0f +# code.cloudfoundry.org/go-diodes v0.0.0-20260504113438-abdf05667e78 ## explicit; go 1.25.0 code.cloudfoundry.org/go-diodes # code.cloudfoundry.org/go-loggregator/v9 v9.2.1 @@ -31,19 +31,19 @@ code.cloudfoundry.org/go-diodes code.cloudfoundry.org/go-loggregator/v9 code.cloudfoundry.org/go-loggregator/v9/rpc/loggregator_v2 code.cloudfoundry.org/go-loggregator/v9/runtimeemitter -# code.cloudfoundry.org/go-metric-registry v0.0.0-20260522085328-be95096762f3 -## explicit; go 1.25.1 +# code.cloudfoundry.org/go-metric-registry v0.0.0-20260505071949-70469c50517d +## explicit; go 1.25.0 code.cloudfoundry.org/go-metric-registry # code.cloudfoundry.org/inigo v0.0.0-20210615140442-4bdc4f6e44d5 ## explicit -# code.cloudfoundry.org/lager/v3 v3.70.0 +# code.cloudfoundry.org/lager/v3 v3.68.0 ## explicit; go 1.25.0 code.cloudfoundry.org/lager/v3 code.cloudfoundry.org/lager/v3/internal/truncate code.cloudfoundry.org/lager/v3/lagerctx code.cloudfoundry.org/lager/v3/lagerflags code.cloudfoundry.org/lager/v3/lagertest -# code.cloudfoundry.org/localip v0.72.0 +# code.cloudfoundry.org/localip v0.70.0 ## explicit; go 1.25.0 code.cloudfoundry.org/localip # code.cloudfoundry.org/locket v0.0.0-20260507165111-20f6e690be22 @@ -61,8 +61,8 @@ code.cloudfoundry.org/locket/lock code.cloudfoundry.org/locket/metrics code.cloudfoundry.org/locket/metrics/helpers code.cloudfoundry.org/locket/models -# code.cloudfoundry.org/tlsconfig v0.55.0 -## explicit; go 1.25.1 +# code.cloudfoundry.org/tlsconfig v0.53.0 +## explicit; go 1.25.0 code.cloudfoundry.org/tlsconfig # filippo.io/edwards25519 v1.2.0 ## explicit; go 1.24.0 @@ -84,7 +84,7 @@ github.com/beorn7/perks/quantile # github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f ## explicit github.com/bmizerany/pat -# github.com/cactus/go-statsd-client v3.2.1+incompatible => github.com/cactus/go-statsd-client v2.0.2-0.20150911070441-6fa055a7b594+incompatible +# github.com/cactus/go-statsd-client v0.0.0-00010101000000-000000000000 => github.com/cactus/go-statsd-client v2.0.2-0.20150911070441-6fa055a7b594+incompatible ## explicit github.com/cactus/go-statsd-client/statsd # github.com/cespare/xxhash/v2 v2.3.0 @@ -170,7 +170,7 @@ github.com/google/go-cmp/cmp/internal/value github.com/google/go-tpm/legacy/tpm2 github.com/google/go-tpm/tpmutil github.com/google/go-tpm/tpmutil/tbs -# github.com/google/pprof v0.0.0-20260507013755-92041b743c96 +# github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 ## explicit; go 1.24.0 github.com/google/pprof/profile # github.com/honeycombio/libhoney-go v1.27.1 @@ -184,7 +184,7 @@ github.com/jackc/pgpassfile # github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 ## explicit; go 1.14 github.com/jackc/pgservicefile -# github.com/jackc/pgx/v5 v5.9.2 +# github.com/jackc/pgx/v5 v5.9.1 ## explicit; go 1.25.0 github.com/jackc/pgx/v5 github.com/jackc/pgx/v5/internal/iobufpool @@ -208,8 +208,8 @@ github.com/jinzhu/inflection # github.com/jinzhu/now v1.1.5 ## explicit; go 1.12 github.com/jinzhu/now -# github.com/kisielk/errcheck v1.20.0 -## explicit; go 1.25.0 +# github.com/kisielk/errcheck v1.10.0 +## explicit; go 1.22.0 github.com/kisielk/errcheck github.com/kisielk/errcheck/errcheck # github.com/klauspost/compress v1.18.6 @@ -234,7 +234,7 @@ github.com/munnerz/goautoneg # github.com/nats-io/jwt/v2 v2.8.1 ## explicit; go 1.25.0 github.com/nats-io/jwt/v2 -# github.com/nats-io/nats-server/v2 v2.14.1 +# github.com/nats-io/nats-server/v2 v2.14.0 ## explicit; go 1.25.0 github.com/nats-io/nats-server/v2 github.com/nats-io/nats-server/v2/conf @@ -253,7 +253,7 @@ github.com/nats-io/nats-server/v2/server/stree github.com/nats-io/nats-server/v2/server/sysmem github.com/nats-io/nats-server/v2/server/thw github.com/nats-io/nats-server/v2/server/tpm -# github.com/nats-io/nats.go v1.52.0 +# github.com/nats-io/nats.go v1.51.0 ## explicit; go 1.25.0 github.com/nats-io/nats.go github.com/nats-io/nats.go/encoders/builtin @@ -268,7 +268,7 @@ github.com/nats-io/nuid # github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d ## explicit github.com/nu7hatch/gouuid -# github.com/onsi/ginkgo/v2 v2.29.0 +# github.com/onsi/ginkgo/v2 v2.28.3 ## explicit; go 1.25.0 github.com/onsi/ginkgo/v2 github.com/onsi/ginkgo/v2/config @@ -292,7 +292,7 @@ github.com/onsi/ginkgo/v2/internal/reporters github.com/onsi/ginkgo/v2/internal/testingtproxy github.com/onsi/ginkgo/v2/reporters github.com/onsi/ginkgo/v2/types -# github.com/onsi/gomega v1.41.0 +# github.com/onsi/gomega v1.40.0 ## explicit; go 1.24.0 github.com/onsi/gomega github.com/onsi/gomega/format @@ -376,8 +376,8 @@ github.com/vmihailenco/msgpack/v5/msgpcode github.com/vmihailenco/tagparser/v2 github.com/vmihailenco/tagparser/v2/internal github.com/vmihailenco/tagparser/v2/internal/parser -# go.step.sm/crypto v0.81.0 -## explicit; go 1.25.1 +# go.step.sm/crypto v0.77.9 +## explicit; go 1.25.0 go.step.sm/crypto/fingerprint go.step.sm/crypto/internal/bcrypt_pbkdf go.step.sm/crypto/internal/emoji @@ -410,7 +410,7 @@ go.yaml.in/yaml/v2 # go.yaml.in/yaml/v3 v3.0.4 ## explicit; go 1.16 go.yaml.in/yaml/v3 -# golang.org/x/crypto v0.52.0 +# golang.org/x/crypto v0.51.0 ## explicit; go 1.25.0 golang.org/x/crypto/bcrypt golang.org/x/crypto/blake2b @@ -433,7 +433,7 @@ golang.org/x/crypto/ssh/internal/bcrypt_pbkdf # golang.org/x/mod v0.36.0 ## explicit; go 1.25.0 golang.org/x/mod/semver -# golang.org/x/net v0.55.0 +# golang.org/x/net v0.54.0 ## explicit; go 1.25.0 golang.org/x/net/context golang.org/x/net/html @@ -457,7 +457,7 @@ golang.org/x/oauth2/internal ## explicit; go 1.25.0 golang.org/x/sync/errgroup golang.org/x/sync/semaphore -# golang.org/x/sys v0.45.0 +# golang.org/x/sys v0.44.0 ## explicit; go 1.25.0 golang.org/x/sys/cpu golang.org/x/sys/unix @@ -535,10 +535,10 @@ golang.org/x/tools/internal/stdlib golang.org/x/tools/internal/typeparams golang.org/x/tools/internal/typesinternal golang.org/x/tools/internal/versions -# google.golang.org/genproto/googleapis/rpc v0.0.0-20260523011958-0a33c5d7ca68 +# google.golang.org/genproto/googleapis/rpc v0.0.0-20260504160031-60b97b32f348 ## explicit; go 1.25.0 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.81.1 +# google.golang.org/grpc v1.81.0 ## explicit; go 1.25.0 google.golang.org/grpc google.golang.org/grpc/attributes