diff options
96 files changed, 2721 insertions, 1743 deletions
@@ -1,3 +1,38 @@ +Knot DNS 3.3.6 (2024-06-12) +=========================== + +Features: +--------- + - knotd: configurable control socket backlog size (see 'control.backlog') + - knotd: optional configuration of congruency of generated keytags (see 'policy.keytag-modulo') + - knotc: support for exporting configuration schema in JSON (see 'conf-export') #912 + - mod-dnstap: configuration of sink allows TCP address specification + +Improvements: +------------- + - knotd: last-signed serial is stored to KASP even if not a secondary zone + - knotd: allowed catalog role member in a catalog template configuration + - knotd: some references in a zone configuration can be set empty to override a template + - knotd: allowed zone backup during a zone transaction + - knotd: add remote TSIG key name to outgoing event logs + - knotc: zone backup with '+keysonly' silently uses all defaults as 'off' + - kxdpgun: host name can be used for target specification + - libs: upgraded embedded libngtcp2 to 1.5.0 + - doc: various fixes and updates + +Bugfixes: +--------- + - knotd: reset TCP connection not removed from a connection pool + - knotd: server wrongly tries to remove removed ZONEMD + - knotd: failed to parse empty list from a textual configuration + - knotd: blocking zone signing in combination with an open transaction causes a deadlock + - knotd: missing RCU lock when sending NOTIFY + - kdig: QNAME letter case isn't preserved if IDN is enabled + - kdig: failed to parse empty QNAME (do not fill question section) + - kxdpgun: floating point exception on SIGUSR1 #927 + - libknot: incorrect handling of regular QUIC tokens in incoming initials + - python: failed to set an empty configuration value + Knot DNS 3.3.5 (2024-03-06) =========================== @@ -20,6 +55,7 @@ Bugfixes: - knotd, kzonecheck: failed to validate RRSIG if there are more keys with the same keytag - knotd, kzonecheck: failed to validate zone with more CSK keys - libknot: insufficient check for malformed TCP header options over XDP + - libzscanner: incorrect alpn processing #923 Knot DNS 3.3.4 (2024-01-24) =========================== @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for knot 3.3.5. +# Generated by GNU Autoconf 2.71 for knot 3.3.6. # # Report bugs to <knot-dns@labs.nic.cz>. # @@ -621,8 +621,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='knot' PACKAGE_TARNAME='knot' -PACKAGE_VERSION='3.3.5' -PACKAGE_STRING='knot 3.3.5' +PACKAGE_VERSION='3.3.6' +PACKAGE_STRING='knot 3.3.6' PACKAGE_BUGREPORT='knot-dns@labs.nic.cz' PACKAGE_URL='' @@ -1603,7 +1603,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures knot 3.3.5 to adapt to many kinds of systems. +\`configure' configures knot 3.3.6 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1674,7 +1674,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of knot 3.3.5:";; + short | recursive ) echo "Configuration of knot 3.3.6:";; esac cat <<\_ACEOF @@ -1923,7 +1923,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -knot configure 3.3.5 +knot configure 3.3.6 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2274,7 +2274,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by knot $as_me 3.3.5, which was +It was created by knot $as_me 3.3.6, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3549,7 +3549,7 @@ fi # Define the identity of the package. PACKAGE='knot' - VERSION='3.3.5' + VERSION='3.3.6' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -5269,7 +5269,7 @@ KNOT_VERSION_MAJOR=3 KNOT_VERSION_MINOR=3 -KNOT_VERSION_PATCH=5 +KNOT_VERSION_PATCH=6 # Store ./configure parameters and CFLAGS @@ -21750,7 +21750,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by knot $as_me 3.3.5, which was +This file was extended by knot $as_me 3.3.6, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -21818,7 +21818,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -knot config.status 3.3.5 +knot config.status 3.3.6 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index cff9690..6f5859f 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ AC_PREREQ([2.69]) m4_define([knot_VERSION_MAJOR], 3)dnl m4_define([knot_VERSION_MINOR], 3)dnl -m4_define([knot_VERSION_PATCH], 5)dnl Leave empty if the master branch! +m4_define([knot_VERSION_PATCH], 6)dnl Leave empty if the master branch! m4_include([m4/knot-version.m4]) AC_INIT([knot], [knot_PKG_VERSION], [knot-dns@labs.nic.cz]) diff --git a/distro/pkg/deb-nolibxdp/libknot14.symbols b/distro/pkg/deb-nolibxdp/libknot14.symbols index b6e7caf..174d517 100644 --- a/distro/pkg/deb-nolibxdp/libknot14.symbols +++ b/distro/pkg/deb-nolibxdp/libknot14.symbols @@ -11,6 +11,7 @@ libknot.so.14 libknot14 #MINVER# knot_ctl_accept@Base 3.3.0 knot_ctl_alloc@Base 3.3.0 knot_ctl_bind@Base 3.3.0 + knot_ctl_bind2@Base 3.3.6 knot_ctl_close@Base 3.3.0 knot_ctl_connect@Base 3.3.0 knot_ctl_free@Base 3.3.0 diff --git a/distro/pkg/deb-noxdp/libknot14.symbols b/distro/pkg/deb-noxdp/libknot14.symbols index 9a30548..ba2024a 100644 --- a/distro/pkg/deb-noxdp/libknot14.symbols +++ b/distro/pkg/deb-noxdp/libknot14.symbols @@ -10,6 +10,7 @@ libknot.so.14 libknot14 #MINVER# knot_ctl_accept@Base 3.3.0 knot_ctl_alloc@Base 3.3.0 knot_ctl_bind@Base 3.3.0 + knot_ctl_bind2@Base 3.3.6 knot_ctl_close@Base 3.3.0 knot_ctl_connect@Base 3.3.0 knot_ctl_free@Base 3.3.0 diff --git a/distro/pkg/deb/libknot14.symbols b/distro/pkg/deb/libknot14.symbols index b6e7caf..174d517 100644 --- a/distro/pkg/deb/libknot14.symbols +++ b/distro/pkg/deb/libknot14.symbols @@ -11,6 +11,7 @@ libknot.so.14 libknot14 #MINVER# knot_ctl_accept@Base 3.3.0 knot_ctl_alloc@Base 3.3.0 knot_ctl_bind@Base 3.3.0 + knot_ctl_bind2@Base 3.3.6 knot_ctl_close@Base 3.3.0 knot_ctl_connect@Base 3.3.0 knot_ctl_free@Base 3.3.0 diff --git a/distro/pkg/rpm/knot.spec b/distro/pkg/rpm/knot.spec index a5c1384..3a7d89e 100644 --- a/distro/pkg/rpm/knot.spec +++ b/distro/pkg/rpm/knot.spec @@ -75,6 +75,10 @@ Requires(postun): systemd Requires: %{name}-libs%{?_isa} = %{version}-%{release} +%if 0%{?suse_version} +Provides: group(knot) +%endif + %description Knot DNS is a high-performance authoritative DNS server implementation. diff --git a/doc/configuration.rst b/doc/configuration.rst index 55457eb..a29521b 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -89,15 +89,15 @@ zones. There is no inheritance between templates; they are exclusive. The Access control list (ACL) ========================= -Some types of incoming DNS requests must be authorized before they can be -processed by the server. A zone can have configured :ref:`zone_acl` which is -a sequence of :ref:`rules <ACL section>` describing what requests are authorized. -By default if :ref:`automatic ACL <server_automatic-acl>` is not enabled, all requests, -which require authorization, are denied. - -Every ACL rule can allow or deny one or more request types based on the -source IP address, network subnet, or address range and/or if the request is -secured by a given TSIG key. See :doc:`keymgr -t<man_keymgr>` on how +Normal DNS queries are always allowed. All other DNS requests must be +authorized before they can be processed by the server. A zone can have +configured :ref:`ACL <ACL section>` which is a sequence of rules describing +what requests are authorized. An :ref:`automatic ACL <server_automatic-acl>` +feature can be used to simplify ACL management. + +Every ACL rule can allow or deny one or more request types (:ref:`actions <acl_action>`) +based on the source IP address, network subnet, or address range and/or if the +request is secured by a given TSIG key. See :doc:`keymgr -t<man_keymgr>` on how to generate a TSIG key. If there are multiple ACL rules assigned to a zone, they are applied in the diff --git a/doc/man/knot.conf.5in b/doc/man/knot.conf.5in index a951b7c..a9b175e 100644 --- a/doc/man/knot.conf.5in +++ b/doc/man/knot.conf.5in @@ -253,7 +253,7 @@ server: quic\-idle\-close\-timeout: TIME remote\-pool\-limit: INT remote\-pool\-timeout: TIME - remote\-retry\-delay: TIME + remote\-retry\-delay: INT socket\-affinity: BOOL udp\-max\-payload: SIZE udp\-max\-payload\-ipv4: SIZE @@ -809,7 +809,7 @@ Time in seconds, after which any idle connection is forcibly closed. .SS tcp\-resend\-timeout .sp Resend outgoing data packets (with DNS response payload) if not ACKed -before this timeout. +before this timeout (in seconds). .sp \fIMinimum:\fP \fB1\fP .sp @@ -859,6 +859,7 @@ Configuration of the server control interface. .ft C control: listen: STR + backlog: INT timeout: TIME .ft P .fi @@ -869,7 +870,16 @@ control: A UNIX socket \fI\%path\fP where the server listens for control commands. .sp +Change of this parameter requires restart of the Knot server to take effect. +.sp \fIDefault:\fP \fI\%rundir\fP\fB/knot.sock\fP +.SS backlog +.sp +The control UNIX socket listen backlog size. +.sp +Change of this parameter requires restart of the Knot server to take effect. +.sp +\fIDefault:\fP \fB5\fP .SS timeout .sp Maximum time (in seconds) the control socket operations can take. @@ -1436,8 +1446,9 @@ An ordered list of \fI\%references\fP to remote server definitions. .SH ACL SECTION .sp Access control list rule definitions. An ACL rule is a description of one -or more authorized operations (zone transfer request, zone change notification, -and dynamic DNS update) which are allowed to be processed or denied. +or more authorized actions (zone transfer request, zone change notification, +and dynamic DNS update) which are allowed to be processed or denied. Normal +DNS queries are always allowed. .INDENT 0.0 .INDENT 3.5 .sp @@ -1506,7 +1517,7 @@ This option cannot be specified along with the \fI\%address\fP or \fIDefault:\fP not set .SS action .sp -An ordered list of allowed (or denied) actions. +An ordered list of allowed, or denied, actions (request types). .sp Possible values: .INDENT 0.0 @@ -1626,8 +1637,8 @@ A DNSSEC\-validating resolver can be set as a parent. .UNINDENT .SS check\-interval .sp -Interval for periodic checks of DS presence on parent\(aqs DNS servers, in the -case of the KSK submission. +Interval (in seconds) for periodic checks of DS presence on parent\(aqs DNS +servers, in the case of the KSK submission. .sp \fIDefault:\fP \fB1h\fP (1 hour) .SS timeout @@ -1639,14 +1650,14 @@ Set to 0 for infinity. \fIDefault:\fP \fB0\fP .SS parent\-delay .sp -After successful parent DS check, wait for this period before continuing the next -key roll\-over step. This delay shall cover the propagation delay of update in the -parent zone. +After successful parent DS check, wait for this period (in seconds) before +continuing the next key roll\-over step. This delay shall cover the propagation +delay of update in the parent zone. .sp \fIDefault:\fP \fB0\fP .SH DNSKEY-SYNC SECTION .sp -Parameters of DNSKEY dynamic\-update synchrnization. +Parameters of DNSKEY dynamic\-update synchronization. .INDENT 0.0 .INDENT 3.5 .sp @@ -1673,7 +1684,7 @@ DNSKEY/CDNSKEY/CDS records shall be sent to. .SS check\-interval .sp If the last DNSKEY sync failed or resulted in any change, re\-check -the consistence after this interval and re\-try if needed. +the consistence after this interval (in seconds) and re\-try if needed. .sp \fIDefault:\fP \fB60\fP (1 minute) .SH POLICY SECTION @@ -1695,6 +1706,7 @@ policy: ksk\-shared: BOOL dnskey\-ttl: TIME zone\-max\-ttl: TIME + keytag\-modulo: INT/INT ksk\-lifetime: TIME zsk\-lifetime: TIME delete\-delay: TIME @@ -1844,9 +1856,26 @@ really reasonable when records are generated dynamically .UNINDENT .sp \fIDefault:\fP computed after zone is loaded +.SS keytag\-modulo +.sp +Specifies that the keytags of any generated keys shall be congruent by specified modulo. +The option value must be a string in the format \fBR/M\fP, where \fBR < M <= 256\fP are +positive integers. Whenever a DNSSEC key is generated, it is ensured +that \fBkeytag % M == R\fP\&. This prevents keytag conflict in \fI\%DNSSEC Offline KSK\fP +or \fI\%DNSSEC multi\-signer\fP (and possibly other) setups. +.sp +\fBNOTE:\fP +.INDENT 0.0 +.INDENT 3.5 +This only applies to newly generated keys when they are generated. Keys from +before this option and keys imported from elsewhere might not fulfill the policy. +.UNINDENT +.UNINDENT +.sp +\fIDefault:\fP \fB0/1\fP .SS ksk\-lifetime .sp -A period between KSK generation and the next rollover initiation. +A period (in seconds) between KSK generation and the next rollover initiation. .sp \fBNOTE:\fP .INDENT 0.0 @@ -1860,10 +1889,10 @@ This applies for CSK lifetime if single\-type\-signing is enabled. .UNINDENT .UNINDENT .sp -\fIDefault:\fP \fB0\fP +\fIDefault:\fP \fB0\fP (infinity) .SS zsk\-lifetime .sp -A period between ZSK activation and the next rollover initiation. +A period (in seconds) between ZSK activation and the next rollover initiation. .sp \fBNOTE:\fP .INDENT 0.0 @@ -1883,20 +1912,20 @@ Zero (aka infinity) value causes no ZSK rollover as a result. .SS delete\-delay .sp Once a key (KSK or ZSK) is rolled\-over and removed from the zone, -keep it in the KASP database for at least this period before deleting it completely. -This might be useful in some troubleshooting cases when resurrection +keep it in the KASP database for at least this period (in seconds) before deleting +it completely. This might be useful in some troubleshooting cases when resurrection is needed. .sp \fIDefault:\fP \fB0\fP .SS propagation\-delay .sp -An extra delay added for each key rollover step. This value should be high -enough to cover propagation of data from the primary server to all -secondary servers, as well as the duration of signing routine itself and -possible outages in signing and propagation infrastructure. In other words, -this delay should ensure that within this period of time after planned -change of the key set, all public\-facing secondaries will already serve -new DNSKEY RRSet for sure. +An extra delay added for each key rollover step. This value (in seconds) +should be high enough to cover propagation of data from the primary server +to all secondary servers, as well as the duration of signing routine itself +and possible outages in signing and propagation infrastructure. In other +words, this delay should ensure that within this period of time after +planned change of the key set, all public\-facing secondaries will already +serve new DNSKEY RRSet for sure. .sp \fBNOTE:\fP .INDENT 0.0 @@ -1908,7 +1937,7 @@ Has influence over ZSK key lifetime. \fIDefault:\fP \fB1h\fP (1 hour) .SS rrsig\-lifetime .sp -A validity period of newly issued signatures. +A validity period (in seconds) of newly issued signatures. .sp \fBNOTE:\fP .INDENT 0.0 @@ -1921,15 +1950,16 @@ time period is not counted to the signature lifetime. \fIDefault:\fP \fB14d\fP (14 days) .SS rrsig\-refresh .sp -A period how long at least before a signature expiration the signature will be refreshed, -in order to prevent expired RRSIGs on secondary servers or resolvers\(aq caches. +A period (in seconds) how long at least before a signature expiration the signature +will be refreshed, in order to prevent expired RRSIGs on secondary servers or +resolvers\(aq caches. .sp \fIDefault:\fP 0.1 * \fI\%rrsig\-lifetime\fP + \fI\%propagation\-delay\fP + \fI\%zone\-max\-ttl\fP .SS rrsig\-pre\-refresh .sp -A period how long at most before a signature refresh time the signature might be refreshed, -in order to refresh RRSIGs in bigger batches on a frequently updated zone -(avoid re\-sign event too often). +A period (in seconds) how long at most before a signature refresh time the signature +might be refreshed, in order to refresh RRSIGs in bigger batches on a frequently updated +zone (avoid re\-sign event too often). .sp \fIDefault:\fP \fB1h\fP (1 hour) .SS reproducible\-signing @@ -1972,7 +2002,7 @@ name before hashing. \fIDefault:\fP \fB8\fP .SS nsec3\-salt\-lifetime .sp -A validity period of newly issued salt field. +A validity period (in seconds) of newly issued salt field. .sp Zero value means infinity. .sp @@ -2308,6 +2338,7 @@ where DDD is corresponding decimal ASCII code. An ordered list of references \fI\%remote\fP and \fI\%remotes\fP to zone primary servers (formerly known as master servers). +Empty value is allowed for template value overriding. .sp \fIDefault:\fP not set .SS ddns\-master @@ -2326,6 +2357,7 @@ combination with \fI\%dnssec\-signing\fP enabled. An ordered list of references \fI\%remote\fP and \fI\%remotes\fP to secondary servers to which notify message is sent if the zone changes. +Empty value is allowed for template value overriding. .sp \fIDefault:\fP not set .SS acl @@ -2339,13 +2371,13 @@ or disallow zone transfers, updates or incoming notifies. If set to a nonzero value on a secondary, always request AXFR/IXFR from the same primary as the last time, effectively pinning one primary. Only when another primary is updated and the current one lags behind for the specified amount of time -(defined by this option), change to the updated primary and force AXFR. +(defined by this option in seconds), change to the updated primary and force AXFR. .sp This option is useful when multiple primaries may have different zone history in their journals, making it unsafe to combine interchanged IXFR from different primaries. .sp -\fIDefault:\fP 0 +\fIDefault:\fP \fB0\fP (disabled) .SS provide\-ixfr .sp If disabled, the server is forced to respond with AXFR to IXFR queries. @@ -2412,8 +2444,8 @@ query (malformed message) and triggers a zone bootstrap instead. \fIDefault:\fP \fBoff\fP .SS zonefile\-sync .sp -The time after which the current zone in memory will be synced with a zone file -on the disk (see \fI\%file\fP). The server will serve the latest +The time in seconds after which the current zone in memory will be synced with +a zone file on the disk (see \fI\%file\fP). The server will serve the latest zone even after a restart using zone journal, but the zone file on the disk will only be synced after \fBzonefile\-sync\fP time has expired (or after manual zone flush). This is applicable when the zone is updated via IXFR, DDNS or automatic @@ -2520,7 +2552,7 @@ Zone\-in\-journal changeset isn\(aqt counted to the limit. If enabled, incoming IXFR is applied even when it contains removals of non\-existing or additions of existing records. .sp -\fIDefault:\fP off +\fIDefault:\fP \fBoff\fP .SS ixfr\-by\-one .sp Within incoming IXFR, process only one changeset at a time, not multiple together. @@ -2615,7 +2647,7 @@ A configured policy called \(dqdefault\(dq won\(aqt be used unless explicitly re .SS ds\-push .sp Per zone configuration of \fI\%ds\-push\fP\&. This option overrides possible -per policy option. +per policy option. Empty value is allowed for template value overriding. .sp \fIDefault:\fP not set .SS zonemd\-verify @@ -2791,9 +2823,8 @@ has the \fIgroup\fP property defined, matching another catalog template. .INDENT 3.5 This option must be set if and only if \fI\%catalog\-role\fP is \fIinterpret\fP\&. .sp -Nested catalog zones aren\(aqt supported. Therefore catalog templates can\(aqt use -\fI\%catalog\-template\fP, \fI\%catalog\-role\fP, \fI\%catalog\-zone\fP, -and \fI\%catalog\-group\fP options. +Nested catalog zones aren\(aqt supported. Therefore catalog templates can\(aqt +contain \fI\%catalog\-role\fP set to \fBinterpret\fP or \fBgenerate\fP\&. .UNINDENT .UNINDENT .sp diff --git a/doc/man/knotc.8in b/doc/man/knotc.8in index 36e7c98..01bfc95 100644 --- a/doc/man/knotc.8in +++ b/doc/man/knotc.8in @@ -103,8 +103,8 @@ public key pin of the currently used certificate. Stop the server if running. .TP \fBreload\fP -Reload the server configuration and modified zone files. All open zone -transactions will be aborted! +Reload the server configuration and modified zone files, and reopen the log files +if they are configured. All open zone transactions will be aborted! .TP \fBstats\fP [\fImodule\fP[\fB\&.\fP\fIcounter\fP]] Show global statistics counter(s). To print also counters with value 0, use @@ -165,13 +165,15 @@ zone\(aqs journal, zone\-related timers, zone\-related data in the KASP database together with keys (or keys without the KASP database), zone\(aqs catalog, and the server QUIC key and certificate, respectively, are backed up, or omitted from the backup. By default, filters \fB+zonefile\fP, \fB+timers\fP, -\fB+kaspdb\fP, \fB+nokeysonly\fP, \fB+catalog\fP, \fB+quic\fP, and \fB+nojournal\fP +\fB+kaspdb\fP, \fB+catalog\fP, \fB+quic\fP, \fB+nojournal\fP, and \fB+nokeysonly\fP are set for backup. The same defaults are set for restore, with the only -difference being \fB+noquic\fP\&. Setting a filter for an item doesn\(aqt change -default settings for other items. If zone flushing is disabled, the original -zone file is backed up instead of writing out zone contents to a file. -When backing\-up a catalog zone, it is recommended to prevent ongoing changes -to it by use of \fBzone\-freeze\fP\&. +difference being \fB+noquic\fP\&. Setting a filter for an item doesn\(aqt change the +default settings for other items. The only exception is \fB+keysonly\fP, which +disables all other filters by default, but they can still be turned on +explicitly. If zone flushing is disabled, the original zone file is backed +up instead of writing out zone contents to a file. When backing\-up a catalog +zone, it is recommended to prevent ongoing changes to it by use of +\fBzone\-freeze\fP\&. See \fI\%Notes\fP below about the directory permissions. (#) .TP \fBzone\-restore\fP [\fIzone\fP\&...] \fB+backupdir\fP \fIdirectory\fP [\fIfilter\fP\&...] @@ -271,8 +273,8 @@ An optional filter \fB+nopurge\fP prevents possibly existing configuration database from purging before the import itself. Also ensure the server is not using the configuration database at the same time! (*) .TP -\fBconf\-export\fP [\fIfilename\fP] -Export the configuration database into a config file or stdout. (*) +\fBconf\-export\fP [\fIfilename\fP] [+schema] +Export the configuration database (or JSON schema) into a file or stdout. (*) .TP \fBconf\-list\fP [\fIitem\fP] List the configuration database sections or section items. diff --git a/doc/man/kxdpgun.8in b/doc/man/kxdpgun.8in index 243f4f4..f93872b 100644 --- a/doc/man/kxdpgun.8in +++ b/doc/man/kxdpgun.8in @@ -32,7 +32,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] kxdpgun \- XDP-powered DNS benchmarking tool .SH SYNOPSIS .sp -\fBkxdpgun\fP [\fIoptions\fP] \fB\-i\fP \fIfilename\fP \fItarget_IP\fP +\fBkxdpgun\fP [\fIoptions\fP] \fB\-i\fP \fIfilename\fP \fItarget\fP .SH DESCRIPTION .sp Powerful generator of DNS traffic, sending and receiving packets through XDP. @@ -50,8 +50,8 @@ configured for the network interface. \fIfilename\fP Path to the queries file. See the description below regarding the file format. .TP -\fItarget_IP\fP -The IPv4 or IPv6 address of remote destination. +\fItarget\fP +Either the domain name, IPv4 or IPv6 address of a remote target. .UNINDENT .SS Options .INDENT 0.0 diff --git a/doc/man_knotc.rst b/doc/man_knotc.rst index f9a5509..d03bc77 100644 --- a/doc/man_knotc.rst +++ b/doc/man_knotc.rst @@ -80,8 +80,8 @@ Actions Stop the server if running. **reload** - Reload the server configuration and modified zone files. All open zone - transactions will be aborted! + Reload the server configuration and modified zone files, and reopen the log files + if they are configured. All open zone transactions will be aborted! **stats** [*module*\ [\ **.**\ *counter*\ ]] Show global statistics counter(s). To print also counters with value 0, use @@ -142,13 +142,15 @@ Actions together with keys (or keys without the KASP database), zone's catalog, and the server QUIC key and certificate, respectively, are backed up, or omitted from the backup. By default, filters **+zonefile**, **+timers**, - **+kaspdb**, **+nokeysonly**, **+catalog**, **+quic**, and **+nojournal** + **+kaspdb**, **+catalog**, **+quic**, **+nojournal**, and **+nokeysonly** are set for backup. The same defaults are set for restore, with the only - difference being **+noquic**. Setting a filter for an item doesn't change - default settings for other items. If zone flushing is disabled, the original - zone file is backed up instead of writing out zone contents to a file. - When backing-up a catalog zone, it is recommended to prevent ongoing changes - to it by use of **zone-freeze**. + difference being **+noquic**. Setting a filter for an item doesn't change the + default settings for other items. The only exception is **+keysonly**, which + disables all other filters by default, but they can still be turned on + explicitly. If zone flushing is disabled, the original zone file is backed + up instead of writing out zone contents to a file. When backing-up a catalog + zone, it is recommended to prevent ongoing changes to it by use of + **zone-freeze**. See :ref:`Notes<notes>` below about the directory permissions. (#) **zone-restore** [*zone*...] **+backupdir** *directory* [*filter*...] @@ -248,8 +250,8 @@ Actions database from purging before the import itself. Also ensure the server is not using the configuration database at the same time! (*) -**conf-export** [*filename*] - Export the configuration database into a config file or stdout. (*) +**conf-export** [*filename*] [+schema] + Export the configuration database (or JSON schema) into a file or stdout. (*) **conf-list** [*item*] List the configuration database sections or section items. diff --git a/doc/man_kxdpgun.rst b/doc/man_kxdpgun.rst index 4664a1e..28713ba 100644 --- a/doc/man_kxdpgun.rst +++ b/doc/man_kxdpgun.rst @@ -6,7 +6,7 @@ Synopsis -------- -:program:`kxdpgun` [*options*] **-i** *filename* *target_IP* +:program:`kxdpgun` [*options*] **-i** *filename* *target* Description ----------- @@ -27,8 +27,8 @@ Parameters *filename* Path to the queries file. See the description below regarding the file format. -*target_IP* - The IPv4 or IPv6 address of remote destination. +*target* + Either the domain name, IPv4 or IPv6 address of a remote target. Options ....... diff --git a/doc/operation.rst b/doc/operation.rst index 43e13ff..5754147 100644 --- a/doc/operation.rst +++ b/doc/operation.rst @@ -831,6 +831,7 @@ For the ZSK side (i.e. the operator of the DNS server), the zone has to be confi - Enabled :ref:`policy_offline-ksk` - Explicit :ref:`policy_dnskey-ttl` - Explicit :ref:`policy_zone-max-ttl` + - Recommended :ref:`policy_keytag-modulo` setting to ``0/2`` to prevent keytag conflicts - Other options are optional - KASP DB may contain a ZSK (the present or some previous one(s)) @@ -841,6 +842,7 @@ For the KSK side (i.e. the operator of the KSK signer), the zone has to be confi - Enabled :ref:`policy_manual` - Enabled :ref:`policy_offline-ksk` - Explicit :ref:`policy_rrsig-refresh` + - Recommended :ref:`policy_keytag-modulo` setting to ``1/2`` to prevent keytag conflicts - Optional :ref:`policy_rrsig-lifetime`, :ref:`policy_rrsig-pre-refresh`, :ref:`policy_algorithm`, :ref:`policy_reproducible-signing`, and :ref:`policy_cds-cdnskey-publish` @@ -957,7 +959,6 @@ within an organization. For multi-signer operations involving multiple "DNSSEC providers" and the ability to switch between them, you can also refer to `MUSIC <https://github.com/DNSSEC-Provisioning/music>`_. - Regardless of the chosen mode from the following options, any secondary that has multiple signers configured as primaries must prevent interchanged IXFR from them. This can be achieved either by setting :ref:`master pinning <zone_master-pin-tolerance>` on every secondary or @@ -965,6 +966,11 @@ by setting distinct :ref:`zone_serial-modulo` on each signer. It is recommended both approaches. Alternatively, if any of the secondaries is not Knot DNS, :ref:`zone_provide-ixfr` can be disabled on the signers. +In order to prevent keytag conflicts, it is recommended that the keytags of keys +generated by each signer are from distinct subset of possible values. With Knot DNS, this +can be achieved using :ref:`policy_keytag-modulo` option (e.g. for three signers, setting +``0/3`` on the first one, ``1/3`` on the second, and ``2/3`` on the third of them). + Sharing private keys, manual policy ----------------------------------- @@ -1170,6 +1176,21 @@ If you want to refresh the secondary zones, you can do this with:: $ knotc zone-refresh +.. _Logging: + +Logging +======= + +Knot DNS supports :ref:`logging<log section>` to ``syslog`` or ``systemd-journald`` +facility, to a specified file, to standard output, or to standard error output. +Several different logging targets may be used in parallel. + +If ``syslog`` or ``systemd-journald`` is used for logging, log rotation is handled +by that logging facility. When logging to a specified file, log rotation should +be done by moving the current log file followed by reopening of the log file with +either ``knotc -b reload`` or by sending ``SIGHUP`` to the ``knotd`` process (see the +:ref:`server_pidfile`). + .. _Data and metadata backup: Data and metadata backup diff --git a/doc/reference.rst b/doc/reference.rst index 45574dc..bbd4586 100644 --- a/doc/reference.rst +++ b/doc/reference.rst @@ -202,7 +202,7 @@ General options related to the server. quic-idle-close-timeout: TIME remote-pool-limit: INT remote-pool-timeout: TIME - remote-retry-delay: TIME + remote-retry-delay: INT socket-affinity: BOOL udp-max-payload: SIZE udp-max-payload-ipv4: SIZE @@ -875,7 +875,7 @@ tcp-resend-timeout ------------------ Resend outgoing data packets (with DNS response payload) if not ACKed -before this timeout. +before this timeout (in seconds). *Minimum:* ``1`` @@ -923,6 +923,7 @@ Configuration of the server control interface. control: listen: STR + backlog: INT timeout: TIME .. _control_listen: @@ -933,8 +934,21 @@ listen A UNIX socket :ref:`path<default_paths>` where the server listens for control commands. +Change of this parameter requires restart of the Knot server to take effect. + *Default:* :ref:`rundir<server_rundir>`\ ``/knot.sock`` +.. _control_backlog: + +backlog +------- + +The control UNIX socket listen backlog size. + +Change of this parameter requires restart of the Knot server to take effect. + +*Default:* ``5`` + .. _control_timeout: timeout @@ -1553,8 +1567,9 @@ An ordered list of :ref:`references<remote_id>` to remote server definitions. =============== Access control list rule definitions. An ACL rule is a description of one -or more authorized operations (zone transfer request, zone change notification, -and dynamic DNS update) which are allowed to be processed or denied. +or more authorized actions (zone transfer request, zone change notification, +and dynamic DNS update) which are allowed to be processed or denied. Normal +DNS queries are always allowed. :: @@ -1637,7 +1652,7 @@ TSIG key if configured must match. action ------ -An ordered list of allowed (or denied) actions. +An ordered list of allowed, or denied, actions (request types). Possible values: @@ -1769,8 +1784,8 @@ rollover must be pushed forward manually. check-interval -------------- -Interval for periodic checks of DS presence on parent's DNS servers, in the -case of the KSK submission. +Interval (in seconds) for periodic checks of DS presence on parent's DNS +servers, in the case of the KSK submission. *Default:* ``1h`` (1 hour) @@ -1790,9 +1805,9 @@ Set to 0 for infinity. parent-delay ------------ -After successful parent DS check, wait for this period before continuing the next -key roll-over step. This delay shall cover the propagation delay of update in the -parent zone. +After successful parent DS check, wait for this period (in seconds) before +continuing the next key roll-over step. This delay shall cover the propagation +delay of update in the parent zone. *Default:* ``0`` @@ -1801,7 +1816,7 @@ parent zone. ``dnskey-sync`` section ======================= -Parameters of DNSKEY dynamic-update synchrnization. +Parameters of DNSKEY dynamic-update synchronization. :: @@ -1834,7 +1849,7 @@ check-interval -------------- If the last DNSKEY sync failed or resulted in any change, re-check -the consistence after this interval and re-try if needed. +the consistence after this interval (in seconds) and re-try if needed. *Default:* ``60`` (1 minute) @@ -1858,6 +1873,7 @@ DNSSEC policy configuration. ksk-shared: BOOL dnskey-ttl: TIME zone-max-ttl: TIME + keytag-modulo: INT/INT ksk-lifetime: TIME zsk-lifetime: TIME delete-delay: TIME @@ -2011,12 +2027,29 @@ Declare (override) maximal TTL value among all the records in zone. *Default:* computed after zone is loaded +.. _policy_keytag-modulo: + +keytag-modulo +------------- + +Specifies that the keytags of any generated keys shall be congruent by specified modulo. +The option value must be a string in the format ``R/M``, where ``R < M <= 256`` are +positive integers. Whenever a DNSSEC key is generated, it is ensured +that ``keytag % M == R``. This prevents keytag conflict in :ref:`DNSSEC Offline KSK` +or :ref:`DNSSEC multi-signer` (and possibly other) setups. + +.. NOTE:: + This only applies to newly generated keys when they are generated. Keys from + before this option and keys imported from elsewhere might not fulfill the policy. + +*Default:* ``0/1`` + .. _policy_ksk-lifetime: ksk-lifetime ------------ -A period between KSK generation and the next rollover initiation. +A period (in seconds) between KSK generation and the next rollover initiation. .. NOTE:: KSK key lifetime is also influenced by propagation-delay, dnskey-ttl, @@ -2026,14 +2059,14 @@ A period between KSK generation and the next rollover initiation. This applies for CSK lifetime if single-type-signing is enabled. -*Default:* ``0`` +*Default:* ``0`` (infinity) .. _policy_zsk-lifetime: zsk-lifetime ------------ -A period between ZSK activation and the next rollover initiation. +A period (in seconds) between ZSK activation and the next rollover initiation. .. NOTE:: More exactly, this period is measured since a ZSK is activated, @@ -2053,8 +2086,8 @@ delete-delay ------------ Once a key (KSK or ZSK) is rolled-over and removed from the zone, -keep it in the KASP database for at least this period before deleting it completely. -This might be useful in some troubleshooting cases when resurrection +keep it in the KASP database for at least this period (in seconds) before deleting +it completely. This might be useful in some troubleshooting cases when resurrection is needed. *Default:* ``0`` @@ -2064,13 +2097,13 @@ is needed. propagation-delay ----------------- -An extra delay added for each key rollover step. This value should be high -enough to cover propagation of data from the primary server to all -secondary servers, as well as the duration of signing routine itself and -possible outages in signing and propagation infrastructure. In other words, -this delay should ensure that within this period of time after planned -change of the key set, all public-facing secondaries will already serve -new DNSKEY RRSet for sure. +An extra delay added for each key rollover step. This value (in seconds) +should be high enough to cover propagation of data from the primary server +to all secondary servers, as well as the duration of signing routine itself +and possible outages in signing and propagation infrastructure. In other +words, this delay should ensure that within this period of time after +planned change of the key set, all public-facing secondaries will already +serve new DNSKEY RRSet for sure. .. NOTE:: Has influence over ZSK key lifetime. @@ -2082,7 +2115,7 @@ new DNSKEY RRSet for sure. rrsig-lifetime -------------- -A validity period of newly issued signatures. +A validity period (in seconds) of newly issued signatures. .. NOTE:: The RRSIG's signature inception time is set to 90 minutes in the past. This @@ -2095,8 +2128,9 @@ A validity period of newly issued signatures. rrsig-refresh ------------- -A period how long at least before a signature expiration the signature will be refreshed, -in order to prevent expired RRSIGs on secondary servers or resolvers' caches. +A period (in seconds) how long at least before a signature expiration the signature +will be refreshed, in order to prevent expired RRSIGs on secondary servers or +resolvers' caches. *Default:* 0.1 * :ref:`policy_rrsig-lifetime` + :ref:`policy_propagation-delay` + :ref:`policy_zone-max-ttl` @@ -2105,9 +2139,9 @@ in order to prevent expired RRSIGs on secondary servers or resolvers' caches. rrsig-pre-refresh ----------------- -A period how long at most before a signature refresh time the signature might be refreshed, -in order to refresh RRSIGs in bigger batches on a frequently updated zone -(avoid re-sign event too often). +A period (in seconds) how long at most before a signature refresh time the signature +might be refreshed, in order to refresh RRSIGs in bigger batches on a frequently updated +zone (avoid re-sign event too often). *Default:* ``1h`` (1 hour) @@ -2170,7 +2204,7 @@ name before hashing. nsec3-salt-lifetime ------------------- -A validity period of newly issued salt field. +A validity period (in seconds) of newly issued salt field. Zero value means infinity. @@ -2494,6 +2528,7 @@ master An ordered list of references :ref:`remote<remote_id>` and :ref:`remotes<remotes_id>` to zone primary servers (formerly known as master servers). +Empty value is allowed for template value overriding. *Default:* not set @@ -2520,6 +2555,7 @@ notify An ordered list of references :ref:`remote<remote_id>` and :ref:`remotes<remotes_id>` to secondary servers to which notify message is sent if the zone changes. +Empty value is allowed for template value overriding. *Default:* not set @@ -2541,13 +2577,13 @@ master-pin-tolerance If set to a nonzero value on a secondary, always request AXFR/IXFR from the same primary as the last time, effectively pinning one primary. Only when another primary is updated and the current one lags behind for the specified amount of time -(defined by this option), change to the updated primary and force AXFR. +(defined by this option in seconds), change to the updated primary and force AXFR. This option is useful when multiple primaries may have different zone history in their journals, making it unsafe to combine interchanged IXFR from different primaries. -*Default:* 0 +*Default:* ``0`` (disabled) .. _zone_provide-ixfr: @@ -2608,8 +2644,8 @@ Extra checks: zonefile-sync ------------- -The time after which the current zone in memory will be synced with a zone file -on the disk (see :ref:`file<zone_file>`). The server will serve the latest +The time in seconds after which the current zone in memory will be synced with +a zone file on the disk (see :ref:`file<zone_file>`). The server will serve the latest zone even after a restart using zone journal, but the zone file on the disk will only be synced after ``zonefile-sync`` time has expired (or after manual zone flush). This is applicable when the zone is updated via IXFR, DDNS or automatic @@ -2707,7 +2743,7 @@ ixfr-benevolent If enabled, incoming IXFR is applied even when it contains removals of non-existing or additions of existing records. -*Default:* off +*Default:* ``off`` .. _zone_ixfr-by-one: @@ -2821,7 +2857,7 @@ ds-push ------- Per zone configuration of :ref:`policy_ds-push`. This option overrides possible -per policy option. +per policy option. Empty value is allowed for template value overriding. *Default:* not set @@ -3014,9 +3050,8 @@ has the *group* property defined, matching another catalog template. .. NOTE:: This option must be set if and only if :ref:`zone_catalog-role` is *interpret*. - Nested catalog zones aren't supported. Therefore catalog templates can't use - :ref:`zone_catalog-template`, :ref:`zone_catalog-role`, :ref:`zone_catalog-zone`, - and :ref:`zone_catalog-group` options. + Nested catalog zones aren't supported. Therefore catalog templates can't + contain :ref:`zone_catalog-role` set to ``interpret`` or ``generate``. *Default:* not set diff --git a/python/libknot/libknot/control.py b/python/libknot/libknot/control.py index 44aa516..659aba8 100644 --- a/python/libknot/libknot/control.py +++ b/python/libknot/libknot/control.py @@ -70,7 +70,7 @@ class KnotCtlData(object): def __setitem__(self, index: KnotCtlDataIdx, value: str) -> None: """Data unit item setter.""" - self.data[index] = ctypes.c_char_p(value.encode()) if value else ctypes.c_char_p() + self.data[index] = ctypes.c_char_p(value.encode()) if value != None else ctypes.c_char_p() class KnotCtlError(Exception): diff --git a/src/Makefile.in b/src/Makefile.in index df978b4..0018a7d 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -493,8 +493,6 @@ am__libembngtcp2_la_SOURCES_DIST = \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conv.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conv.h \ - contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c \ - contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_err.c \ @@ -545,10 +543,14 @@ am__libembngtcp2_la_SOURCES_DIST = \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.h \ + contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c \ + contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h \ + contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c \ + contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_tstamp.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.h \ @@ -572,7 +574,6 @@ am__libembngtcp2_la_SOURCES_DIST = \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_cid.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conn.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conv.lo \ -@EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conversion.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_crypto.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_err.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_frame_chain.lo \ @@ -596,8 +597,10 @@ am__libembngtcp2_la_SOURCES_DIST = \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_rob.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_rst.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_rtb.lo \ +@EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_settings.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_str.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_strm.lo \ +@EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_transport_params.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_unreachable.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_vec.lo \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_version.lo \ @@ -1149,7 +1152,6 @@ am__depfiles_remade = contrib/$(DEPDIR)/libcontrib_la-base32hex.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_cid.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conn.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conv.Plo \ - contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conversion.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_crypto.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_err.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_frame_chain.Plo \ @@ -1173,8 +1175,10 @@ am__depfiles_remade = contrib/$(DEPDIR)/libcontrib_la-base32hex.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rob.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rst.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rtb.Plo \ + contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_settings.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_str.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_strm.Plo \ + contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_transport_params.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_unreachable.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_vec.Plo \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_version.Plo \ @@ -1961,8 +1965,6 @@ libcontrib_la_SOURCES = \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conv.c \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conv.h \ -@EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c \ -@EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.h \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_err.c \ @@ -2013,10 +2015,14 @@ libcontrib_la_SOURCES = \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.h \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.h \ +@EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c \ +@EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h \ +@EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c \ +@EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.h \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_tstamp.h \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.c \ @EMBEDDED_LIBNGTCP2_TRUE@ contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.h \ @@ -3191,9 +3197,6 @@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conn.lo: \ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conv.lo: \ contrib/libngtcp2/ngtcp2/lib/$(am__dirstamp) \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/$(am__dirstamp) -contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conversion.lo: \ - contrib/libngtcp2/ngtcp2/lib/$(am__dirstamp) \ - contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/$(am__dirstamp) contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_crypto.lo: \ contrib/libngtcp2/ngtcp2/lib/$(am__dirstamp) \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/$(am__dirstamp) @@ -3263,12 +3266,18 @@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_rst.lo: \ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_rtb.lo: \ contrib/libngtcp2/ngtcp2/lib/$(am__dirstamp) \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/$(am__dirstamp) +contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_settings.lo: \ + contrib/libngtcp2/ngtcp2/lib/$(am__dirstamp) \ + contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/$(am__dirstamp) contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_str.lo: \ contrib/libngtcp2/ngtcp2/lib/$(am__dirstamp) \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/$(am__dirstamp) contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_strm.lo: \ contrib/libngtcp2/ngtcp2/lib/$(am__dirstamp) \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/$(am__dirstamp) +contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_transport_params.lo: \ + contrib/libngtcp2/ngtcp2/lib/$(am__dirstamp) \ + contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/$(am__dirstamp) contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_unreachable.lo: \ contrib/libngtcp2/ngtcp2/lib/$(am__dirstamp) \ contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/$(am__dirstamp) @@ -4197,7 +4206,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_cid.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conn.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conv.Plo@am__quote@ # am--include-marker -@AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conversion.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_crypto.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_err.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_frame_chain.Plo@am__quote@ # am--include-marker @@ -4221,8 +4229,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rob.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rst.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rtb.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_settings.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_str.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_strm.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_transport_params.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_unreachable.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_vec.Plo@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_version.Plo@am__quote@ # am--include-marker @@ -5110,13 +5120,6 @@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conv.lo: contrib/libngtcp2/n @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conv.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_conv.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_conv.c -contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conversion.lo: contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conversion.lo -MD -MP -MF contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conversion.Tpo -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conversion.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conversion.Tpo contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conversion.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c' object='contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conversion.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_conversion.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c - contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_crypto.lo: contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_crypto.lo -MD -MP -MF contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_crypto.Tpo -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_crypto.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_crypto.Tpo contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_crypto.Plo @@ -5278,6 +5281,13 @@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_rtb.lo: contrib/libngtcp2/ng @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_rtb.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c +contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_settings.lo: contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_settings.lo -MD -MP -MF contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_settings.Tpo -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_settings.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_settings.Tpo contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_settings.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c' object='contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_settings.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_settings.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c + contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_str.lo: contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_str.lo -MD -MP -MF contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_str.Tpo -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_str.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_str.Tpo contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_str.Plo @@ -5292,6 +5302,13 @@ contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_strm.lo: contrib/libngtcp2/n @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_strm.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c +contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_transport_params.lo: contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_transport_params.lo -MD -MP -MF contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_transport_params.Tpo -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_transport_params.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_transport_params.Tpo contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_transport_params.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c' object='contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_transport_params.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_transport_params.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c + contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_unreachable.lo: contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libembngtcp2_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_unreachable.lo -MD -MP -MF contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_unreachable.Tpo -c -o contrib/libngtcp2/ngtcp2/lib/libembngtcp2_la-ngtcp2_unreachable.lo `test -f 'contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.c' || echo '$(srcdir)/'`contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_unreachable.Tpo contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_unreachable.Plo @@ -7492,7 +7509,6 @@ distclean: distclean-recursive -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_cid.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conn.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conv.Plo - -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conversion.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_crypto.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_err.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_frame_chain.Plo @@ -7516,8 +7532,10 @@ distclean: distclean-recursive -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rob.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rst.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rtb.Plo + -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_settings.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_str.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_strm.Plo + -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_transport_params.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_unreachable.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_vec.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_version.Plo @@ -7859,7 +7877,6 @@ maintainer-clean: maintainer-clean-recursive -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_cid.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conn.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conv.Plo - -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_conversion.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_crypto.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_err.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_frame_chain.Plo @@ -7883,8 +7900,10 @@ maintainer-clean: maintainer-clean-recursive -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rob.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rst.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_rtb.Plo + -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_settings.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_str.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_strm.Plo + -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_transport_params.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_unreachable.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_vec.Plo -rm -f contrib/libngtcp2/ngtcp2/lib/$(DEPDIR)/libembngtcp2_la-ngtcp2_version.Plo diff --git a/src/contrib/Makefile.inc b/src/contrib/Makefile.inc index c316b5f..e1577d5 100644 --- a/src/contrib/Makefile.inc +++ b/src/contrib/Makefile.inc @@ -151,8 +151,6 @@ libembngtcp2_la_SOURCES = \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn_stat.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conv.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_conv.h \ - contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c \ - contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_err.c \ @@ -203,10 +201,14 @@ libembngtcp2_la_SOURCES = \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_rst.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.h \ + contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c \ + contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_str.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h \ + contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c \ + contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_tstamp.h \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.c \ contrib/libngtcp2/ngtcp2/lib/ngtcp2_unreachable.h \ diff --git a/src/contrib/conn_pool.c b/src/contrib/conn_pool.c index a344c57..6f61e09 100644 --- a/src/contrib/conn_pool.c +++ b/src/contrib/conn_pool.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,6 +15,7 @@ */ #include <assert.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -255,8 +256,9 @@ void conn_pool_close_cb_dflt(conn_pool_fd_t fd) bool conn_pool_invalid_cb_dflt(conn_pool_fd_t fd) { uint8_t unused; + errno = 0; int peek = recv((int)fd, &unused, 1, MSG_PEEK | MSG_DONTWAIT); - return (peek >= 0); // closed or pending data + return (peek == 0 || peek > 0 || errno == ECONNRESET); // closed || pending data || reset (alternative: errno != 0 && errno != EAGAIN) } bool conn_pool_invalid_cb_allvalid(conn_pool_fd_t fd) diff --git a/src/contrib/json.c b/src/contrib/json.c index 3a35fc6..d44da87 100644 --- a/src/contrib/json.c +++ b/src/contrib/json.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,7 +22,7 @@ #include "contrib/string.h" -#define MAX_DEPTH 8 +#define MAX_DEPTH 16 enum { BLOCK_INVALID = 0, diff --git a/src/contrib/libngtcp2/ngtcp2/crypto/shared.c b/src/contrib/libngtcp2/ngtcp2/crypto/shared.c index 162094a..604cb96 100644 --- a/src/contrib/libngtcp2/ngtcp2/crypto/shared.c +++ b/src/contrib/libngtcp2/ngtcp2/crypto/shared.c @@ -923,10 +923,11 @@ ngtcp2_ssize ngtcp2_crypto_generate_retry_token( uint8_t *token, const uint8_t *secret, size_t secretlen, uint32_t version, const ngtcp2_sockaddr *remote_addr, ngtcp2_socklen remote_addrlen, const ngtcp2_cid *retry_scid, const ngtcp2_cid *odcid, ngtcp2_tstamp ts) { - uint8_t plaintext[NGTCP2_CRYPTO_MAX_RETRY_TOKENLEN]; + uint8_t + plaintext[/* cid len = */ 1 + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp)]; uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN]; - uint8_t key[32]; - uint8_t iv[32]; + uint8_t key[16]; + uint8_t iv[12]; size_t keylen; size_t ivlen; ngtcp2_crypto_aead aead; @@ -962,8 +963,8 @@ ngtcp2_ssize ngtcp2_crypto_generate_retry_token( keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); - assert(sizeof(key) >= keylen); - assert(sizeof(iv) >= ivlen); + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, rand_data, sizeof(rand_data), @@ -1005,8 +1006,8 @@ int ngtcp2_crypto_verify_retry_token( const ngtcp2_cid *dcid, ngtcp2_duration timeout, ngtcp2_tstamp ts) { uint8_t plaintext[/* cid len = */ 1 + NGTCP2_MAX_CIDLEN + sizeof(ngtcp2_tstamp)]; - uint8_t key[32]; - uint8_t iv[32]; + uint8_t key[16]; + uint8_t iv[12]; size_t keylen; size_t ivlen; ngtcp2_crypto_aead_ctx aead_ctx; @@ -1039,6 +1040,9 @@ int ngtcp2_crypto_verify_retry_token( keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); + if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN, retry_token_info_prefix, @@ -1114,8 +1118,8 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token( ngtcp2_tstamp ts) { uint8_t plaintext[sizeof(ngtcp2_tstamp)]; uint8_t rand_data[NGTCP2_CRYPTO_TOKEN_RAND_DATALEN]; - uint8_t key[32]; - uint8_t iv[32]; + uint8_t key[16]; + uint8_t iv[12]; size_t keylen; size_t ivlen; ngtcp2_crypto_aead aead; @@ -1144,8 +1148,8 @@ ngtcp2_ssize ngtcp2_crypto_generate_regular_token( keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); - assert(sizeof(key) >= keylen); - assert(sizeof(iv) >= ivlen); + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, rand_data, sizeof(rand_data), @@ -1186,8 +1190,8 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, ngtcp2_duration timeout, ngtcp2_tstamp ts) { uint8_t plaintext[sizeof(ngtcp2_tstamp)]; - uint8_t key[32]; - uint8_t iv[32]; + uint8_t key[16]; + uint8_t iv[12]; size_t keylen; size_t ivlen; ngtcp2_crypto_aead_ctx aead_ctx; @@ -1217,6 +1221,9 @@ int ngtcp2_crypto_verify_regular_token(const uint8_t *token, size_t tokenlen, keylen = ngtcp2_crypto_aead_keylen(&aead); ivlen = ngtcp2_crypto_aead_noncelen(&aead); + assert(sizeof(key) == keylen); + assert(sizeof(iv) == ivlen); + if (crypto_derive_token_key(key, keylen, iv, ivlen, &md, secret, secretlen, rand_data, NGTCP2_CRYPTO_TOKEN_RAND_DATALEN, regular_token_info_prefix, diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c index d4778d6..3ed581f 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.c @@ -60,31 +60,18 @@ static int greater(const ngtcp2_ksl_key *lhs, const ngtcp2_ksl_key *rhs) { return *(int64_t *)lhs > *(int64_t *)rhs; } -int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, - const ngtcp2_mem *mem) { - int rv; - +void ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, + const ngtcp2_mem *mem) { ngtcp2_objalloc_acktr_entry_init(&acktr->objalloc, 32, mem); - rv = ngtcp2_ringbuf_init(&acktr->acks, 32, sizeof(ngtcp2_acktr_ack_entry), - mem); - if (rv != 0) { - goto fail_acks_init; - } + ngtcp2_static_ringbuf_acks_init(&acktr->acks); ngtcp2_ksl_init(&acktr->ents, greater, sizeof(int64_t), mem); acktr->log = log; - acktr->mem = mem; acktr->flags = NGTCP2_ACKTR_FLAG_NONE; acktr->first_unacked_ts = UINT64_MAX; acktr->rx_npkt = 0; - - return 0; - -fail_acks_init: - ngtcp2_objalloc_free(&acktr->objalloc); - return rv; } void ngtcp2_acktr_free(ngtcp2_acktr *acktr) { @@ -105,8 +92,6 @@ void ngtcp2_acktr_free(ngtcp2_acktr *acktr) { ngtcp2_ksl_free(&acktr->ents); - ngtcp2_ringbuf_free(&acktr->acks); - ngtcp2_objalloc_free(&acktr->objalloc); } @@ -225,7 +210,7 @@ int ngtcp2_acktr_empty(ngtcp2_acktr *acktr) { ngtcp2_acktr_ack_entry *ngtcp2_acktr_add_ack(ngtcp2_acktr *acktr, int64_t pkt_num, int64_t largest_ack) { - ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks); + ngtcp2_acktr_ack_entry *ent = ngtcp2_ringbuf_push_front(&acktr->acks.rb); ent->largest_ack = largest_ack; ent->pkt_num = pkt_num; @@ -266,8 +251,10 @@ static void acktr_on_ack(ngtcp2_acktr *acktr, ngtcp2_ringbuf *rb, ngtcp2_ksl_it_prev(&it); ent = ngtcp2_ksl_it_get(&it); - if (ent->pkt_num > ack_ent->largest_ack && - ack_ent->largest_ack >= ent->pkt_num - (int64_t)(ent->len - 1)) { + + assert(ent->pkt_num > ack_ent->largest_ack); + + if (ack_ent->largest_ack >= ent->pkt_num - (int64_t)(ent->len - 1)) { ent->len = (size_t)(ent->pkt_num - ack_ent->largest_ack); } } @@ -279,7 +266,7 @@ void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) { ngtcp2_acktr_ack_entry *ent; int64_t largest_ack = fr->largest_ack, min_ack; size_t i, j; - ngtcp2_ringbuf *rb = &acktr->acks; + ngtcp2_ringbuf *rb = &acktr->acks.rb; size_t nacks = ngtcp2_ringbuf_len(rb); /* Assume that ngtcp2_pkt_validate_ack(fr) returns 0 */ @@ -306,8 +293,7 @@ void ngtcp2_acktr_recv_ack(ngtcp2_acktr *acktr, const ngtcp2_ack *fr) { for (;;) { if (ent->pkt_num > largest_ack) { - ++j; - if (j == nacks) { + if (++j == nacks) { return; } ent = ngtcp2_ringbuf_get(rb, j); diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.h index 809fb69..0cbb490 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_acktr.h @@ -108,17 +108,18 @@ typedef struct ngtcp2_acktr_ack_entry { expired and canceled. */ #define NGTCP2_ACKTR_FLAG_CANCEL_TIMER 0x0100u +ngtcp2_static_ringbuf_def(acks, 32, sizeof(ngtcp2_acktr_ack_entry)); + /* * ngtcp2_acktr tracks received packets which we have to send ack. */ typedef struct ngtcp2_acktr { ngtcp2_objalloc objalloc; - ngtcp2_ringbuf acks; + ngtcp2_static_ringbuf_acks acks; /* ents includes ngtcp2_acktr_entry sorted by decreasing order of packet number. */ ngtcp2_ksl ents; ngtcp2_log *log; - const ngtcp2_mem *mem; /* flags is bitwise OR of zero, or more of NGTCP2_ACKTR_FLAG_*. */ uint16_t flags; /* first_unacked_ts is timestamp when ngtcp2_acktr_entry is added @@ -131,15 +132,9 @@ typedef struct ngtcp2_acktr { /* * ngtcp2_acktr_init initializes |acktr|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. */ -int ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, - const ngtcp2_mem *mem); +void ngtcp2_acktr_init(ngtcp2_acktr *acktr, ngtcp2_log *log, + const ngtcp2_mem *mem); /* * ngtcp2_acktr_free frees resources allocated for |acktr|. It frees diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c index 27c4667..ebc6f48 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_bbr.c @@ -558,11 +558,12 @@ static void bbr_init_lower_bounds(ngtcp2_cc_bbr *bbr, ngtcp2_conn_stat *cstat) { } static void bbr_loss_lower_bounds(ngtcp2_cc_bbr *bbr) { - bbr->bw_lo = ngtcp2_max(bbr->bw_latest, bbr->bw_lo * NGTCP2_BBR_BETA_NUMER / - NGTCP2_BBR_BETA_DENOM); - bbr->inflight_lo = ngtcp2_max(bbr->inflight_latest, - bbr->inflight_lo * NGTCP2_BBR_BETA_NUMER / - NGTCP2_BBR_BETA_DENOM); + bbr->bw_lo = + ngtcp2_max_uint64(bbr->bw_latest, bbr->bw_lo * NGTCP2_BBR_BETA_NUMER / + NGTCP2_BBR_BETA_DENOM); + bbr->inflight_lo = ngtcp2_max_uint64( + bbr->inflight_latest, + bbr->inflight_lo * NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM); } static void bbr_bound_bw_for_model(ngtcp2_cc_bbr *bbr) { @@ -801,13 +802,13 @@ static uint64_t bbr_inflight_with_headroom(ngtcp2_cc_bbr *bbr, return UINT64_MAX; } - headroom = ngtcp2_max(cstat->max_tx_udp_payload_size, - bbr->inflight_hi * NGTCP2_BBR_HEADROOM_NUMER / - NGTCP2_BBR_HEADROOM_DENOM); + headroom = ngtcp2_max_uint64(cstat->max_tx_udp_payload_size, + bbr->inflight_hi * NGTCP2_BBR_HEADROOM_NUMER / + NGTCP2_BBR_HEADROOM_DENOM); mpcwnd = min_pipe_cwnd(cstat->max_tx_udp_payload_size); if (bbr->inflight_hi > headroom) { - return ngtcp2_max(bbr->inflight_hi - headroom, mpcwnd); + return ngtcp2_max_uint64(bbr->inflight_hi - headroom, mpcwnd); } return mpcwnd; @@ -818,8 +819,8 @@ static void bbr_raise_inflight_hi_slope(ngtcp2_cc_bbr *bbr, uint64_t growth_this_round = cstat->max_tx_udp_payload_size << bbr->bw_probe_up_rounds; - bbr->bw_probe_up_rounds = ngtcp2_min(bbr->bw_probe_up_rounds + 1, 30); - bbr->probe_up_cnt = ngtcp2_max(cstat->cwnd / growth_this_round, 1) * + bbr->bw_probe_up_rounds = ngtcp2_min_size(bbr->bw_probe_up_rounds + 1, 30); + bbr->probe_up_cnt = ngtcp2_max_uint64(cstat->cwnd / growth_this_round, 1) * cstat->max_tx_udp_payload_size; } @@ -946,7 +947,7 @@ static void bbr_handle_inflight_too_high(ngtcp2_cc_bbr *bbr, bbr->bw_probe_samples = 0; if (!rs->is_app_limited) { - bbr->inflight_hi = ngtcp2_max( + bbr->inflight_hi = ngtcp2_max_uint64( rs->tx_in_flight, bbr_target_inflight(bbr, cstat) * NGTCP2_BBR_BETA_NUMER / NGTCP2_BBR_BETA_DENOM); } @@ -1154,8 +1155,8 @@ static uint64_t bbr_quantization_budget(ngtcp2_cc_bbr *bbr, bbr_update_offload_budget(bbr, cstat); inflight = ngtcp2_max(inflight, bbr->offload_budget); - inflight = - ngtcp2_max(inflight, min_pipe_cwnd(cstat->max_tx_udp_payload_size)); + inflight = ngtcp2_max_uint64(inflight, + min_pipe_cwnd(cstat->max_tx_udp_payload_size)); if (bbr->state == NGTCP2_BBR_STATE_PROBE_BW_UP) { inflight += 2 * cstat->max_tx_udp_payload_size; @@ -1198,15 +1199,16 @@ static void bbr_modulate_cwnd_for_recovery(ngtcp2_cc_bbr *bbr, if (ack->bytes_lost > 0) { if (cstat->cwnd > ack->bytes_lost) { cstat->cwnd -= ack->bytes_lost; - cstat->cwnd = ngtcp2_max(cstat->cwnd, 2 * cstat->max_tx_udp_payload_size); + cstat->cwnd = + ngtcp2_max_uint64(cstat->cwnd, 2 * cstat->max_tx_udp_payload_size); } else { cstat->cwnd = 2 * cstat->max_tx_udp_payload_size; } } if (bbr->packet_conservation) { - cstat->cwnd = - ngtcp2_max(cstat->cwnd, cstat->bytes_in_flight + ack->bytes_delivered); + cstat->cwnd = ngtcp2_max_uint64(cstat->cwnd, cstat->bytes_in_flight + + ack->bytes_delivered); } } @@ -1400,8 +1402,8 @@ static void bbr_cc_on_persistent_congestion(ngtcp2_cc *cc, bbr_save_cwnd(bbr, cstat); cstat->cwnd = cstat->bytes_in_flight + cstat->max_tx_udp_payload_size; - cstat->cwnd = - ngtcp2_max(cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size)); + cstat->cwnd = ngtcp2_max_uint64( + cstat->cwnd, min_pipe_cwnd(cstat->max_tx_udp_payload_size)); } static void bbr_cc_on_ack_recv(ngtcp2_cc *cc, ngtcp2_conn_stat *cstat, diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c index 9ad37fb..bade016 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_cc.c @@ -41,7 +41,7 @@ uint64_t ngtcp2_cc_compute_initcwnd(size_t max_udp_payload_size) { uint64_t n = 2 * max_udp_payload_size; n = ngtcp2_max(n, 14720); - return ngtcp2_min(10 * max_udp_payload_size, n); + return ngtcp2_min_uint64(10 * max_udp_payload_size, n); } ngtcp2_cc_pkt *ngtcp2_cc_pkt_init(ngtcp2_cc_pkt *pkt, int64_t pkt_num, diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c index c8caf47..a8e8874 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.c @@ -37,7 +37,8 @@ #include "ngtcp2_rcvry.h" #include "ngtcp2_unreachable.h" #include "ngtcp2_net.h" -#include "ngtcp2_conversion.h" +#include "ngtcp2_transport_params.h" +#include "ngtcp2_settings.h" #include "ngtcp2_tstamp.h" #include "ngtcp2_frame_chain.h" @@ -663,13 +664,11 @@ static int conn_call_recv_tx_key(ngtcp2_conn *conn, return 0; } -static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, - ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num, - ngtcp2_log *log, ngtcp2_qlog *qlog, - ngtcp2_objalloc *rtb_entry_objalloc, - ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { - int rv; - +static void pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, + ngtcp2_rst *rst, ngtcp2_cc *cc, int64_t initial_pkt_num, + ngtcp2_log *log, ngtcp2_qlog *qlog, + ngtcp2_objalloc *rtb_entry_objalloc, + ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { memset(pktns, 0, sizeof(*pktns)); ngtcp2_gaptr_init(&pktns->rx.pngap, mem); @@ -679,10 +678,7 @@ static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, pktns->rx.max_pkt_num = -1; pktns->rx.max_ack_eliciting_pkt_num = -1; - rv = ngtcp2_acktr_init(&pktns->acktr, log, mem); - if (rv != 0) { - goto fail_acktr_init; - } + ngtcp2_acktr_init(&pktns->acktr, log, mem); ngtcp2_strm_init(&pktns->crypto.strm, 0, NGTCP2_STRM_FLAG_NONE, 0, 0, NULL, frc_objalloc, mem); @@ -690,13 +686,6 @@ static int pktns_init(ngtcp2_pktns *pktns, ngtcp2_pktns_id pktns_id, ngtcp2_rtb_init(&pktns->rtb, pktns_id, &pktns->crypto.strm, rst, cc, initial_pkt_num, log, qlog, rtb_entry_objalloc, frc_objalloc, mem); - - return 0; - -fail_acktr_init: - ngtcp2_gaptr_free(&pktns->rx.pngap); - - return rv; } static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id, @@ -704,20 +693,15 @@ static int pktns_new(ngtcp2_pktns **ppktns, ngtcp2_pktns_id pktns_id, ngtcp2_log *log, ngtcp2_qlog *qlog, ngtcp2_objalloc *rtb_entry_objalloc, ngtcp2_objalloc *frc_objalloc, const ngtcp2_mem *mem) { - int rv; - *ppktns = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pktns)); if (*ppktns == NULL) { return NGTCP2_ERR_NOMEM; } - rv = pktns_init(*ppktns, pktns_id, rst, cc, initial_pkt_num, log, qlog, - rtb_entry_objalloc, frc_objalloc, mem); - if (rv != 0) { - ngtcp2_mem_free(mem, *ppktns); - } + pktns_init(*ppktns, pktns_id, rst, cc, initial_pkt_num, log, qlog, + rtb_entry_objalloc, frc_objalloc, mem); - return rv; + return 0; } static int cycle_less(const ngtcp2_pq_entry *lhs, const ngtcp2_pq_entry *rhs) { @@ -803,8 +787,9 @@ static void conn_reset_conn_stat_cc(ngtcp2_conn *conn, cstat->first_rtt_sample_ts = UINT64_MAX; cstat->pto_count = 0; cstat->loss_detection_timer = UINT64_MAX; - cstat->cwnd = - ngtcp2_cc_compute_initcwnd(conn->local.settings.max_tx_udp_payload_size); + cstat->max_tx_udp_payload_size = + ngtcp2_conn_get_path_max_tx_udp_payload_size(conn); + cstat->cwnd = ngtcp2_cc_compute_initcwnd(cstat->max_tx_udp_payload_size); cstat->ssthresh = UINT64_MAX; cstat->congestion_recovery_start_ts = UINT64_MAX; cstat->bytes_in_flight = 0; @@ -847,7 +832,7 @@ static void delete_scid(ngtcp2_ksl *scids, const ngtcp2_mem *mem) { static ngtcp2_duration compute_pto(ngtcp2_duration smoothed_rtt, ngtcp2_duration rttvar, ngtcp2_duration max_ack_delay) { - ngtcp2_duration var = ngtcp2_max(4 * rttvar, NGTCP2_GRANULARITY); + ngtcp2_duration var = ngtcp2_max_uint64(4 * rttvar, NGTCP2_GRANULARITY); return smoothed_rtt + var + max_ack_delay; } @@ -1007,28 +992,15 @@ static void conn_reset_ecn_validation_state(ngtcp2_conn *conn) { static uint8_t server_default_available_versions[] = {0, 0, 0, 1}; /* - * available_versions_new allocates new buffer, and writes |versions| - * of length |versionslen| in network byte order, suitable for sending - * in available_versions field of version_information QUIC transport - * parameter. The pointer to the allocated buffer is assigned to - * |*pbuf|. - * - * This function returns 0 if it succeeds, or one of the negative - * error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. + * available_versions_init writes |versions| of length |versionslen| + * in network byte order to the buffer pointed by |buf|, suitable for + * sending in available_versions field of version_information QUIC + * transport parameter. This function returns the pointer to the one + * beyond the last byte written. */ -static int available_versions_new(uint8_t **pbuf, const uint32_t *versions, - size_t versionslen, const ngtcp2_mem *mem) { +static void *available_versions_init(void *buf, const uint32_t *versions, + size_t versionslen) { size_t i; - uint8_t *buf = ngtcp2_mem_malloc(mem, sizeof(uint32_t) * versionslen); - - if (buf == NULL) { - return NGTCP2_ERR_NOMEM; - } - - *pbuf = buf; for (i = 0; i < versionslen; ++i) { buf = ngtcp2_put_uint32be(buf, versions[i]); @@ -1055,6 +1027,16 @@ conn_set_local_transport_params(ngtcp2_conn *conn, p->version_info_present = 1; } +static size_t buflen_align(size_t buflen) { + return (buflen + 0x7) & (size_t)~0x7; +} + +static void *buf_align(void *buf) { + return (void *)((uintptr_t)((uint8_t *)buf + 0x7) & (uintptr_t)~0x7); +} + +static void *buf_advance(void *buf, size_t n) { return (uint8_t *)buf + n; } + static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_cid *scid, const ngtcp2_path *path, uint32_t client_chosen_version, int callbacks_version, @@ -1065,14 +1047,18 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, const ngtcp2_mem *mem, void *user_data, int server) { int rv; ngtcp2_scid *scident; - uint8_t *buf; + void *buf, *tokenbuf; + size_t buflen; uint8_t fixed_bit_byte; size_t i; uint32_t *preferred_versions; + ngtcp2_settings settingsbuf; ngtcp2_transport_params paramsbuf; (void)callbacks_version; (void)settings_version; + settings = ngtcp2_settings_convert_to_latest(&settingsbuf, settings_version, + settings); params = ngtcp2_transport_params_convert_to_latest( ¶msbuf, transport_params_version, params); @@ -1111,16 +1097,54 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, assert(callbacks->get_path_challenge_data); assert(!server || !ngtcp2_is_reserved_version(client_chosen_version)); + for (i = 0; i < settings->pmtud_probeslen; ++i) { + assert(settings->pmtud_probes[i] > NGTCP2_MAX_UDP_PAYLOAD_SIZE); + } + if (mem == NULL) { mem = ngtcp2_mem_default(); } - *pconn = ngtcp2_mem_calloc(mem, 1, sizeof(ngtcp2_conn)); - if (*pconn == NULL) { - rv = NGTCP2_ERR_NOMEM; - goto fail_conn; + buflen = sizeof(ngtcp2_conn); + if (settings->qlog_write) { + buflen = buflen_align(buflen); + buflen += NGTCP2_QLOG_BUFLEN; + } + + if (settings->pmtud_probeslen) { + buflen = buflen_align(buflen); + buflen += sizeof(settings->pmtud_probes[0]) * settings->pmtud_probeslen; + } + + if (settings->preferred_versionslen) { + buflen = buflen_align(buflen); + buflen += sizeof(settings->preferred_versions[0]) * + settings->preferred_versionslen; + } + + if (settings->available_versionslen) { + buflen = buflen_align(buflen); + buflen += sizeof(settings->available_versions[0]) * + settings->available_versionslen; + } else if (server) { + if (settings->preferred_versionslen) { + buflen = buflen_align(buflen); + buflen += sizeof(settings->preferred_versions[0]) * + settings->preferred_versionslen; + } + } else if (!ngtcp2_is_reserved_version(client_chosen_version)) { + buflen = buflen_align(buflen); + buflen += sizeof(client_chosen_version); } + buf = ngtcp2_mem_calloc(mem, 1, buflen); + if (buf == NULL) { + return NGTCP2_ERR_NOMEM; + } + + *pconn = buf; + buf = buf_advance(buf, sizeof(ngtcp2_conn)); + (*pconn)->server = server; ngtcp2_objalloc_frame_chain_init(&(*pconn)->frc_objalloc, 64, mem); @@ -1154,36 +1178,47 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, ngtcp2_qlog_init(&(*pconn)->qlog, settings->qlog_write, settings->initial_ts, user_data); if ((*pconn)->qlog.write) { - buf = ngtcp2_mem_malloc(mem, NGTCP2_QLOG_BUFLEN); - if (buf == NULL) { - rv = NGTCP2_ERR_NOMEM; - goto fail_qlog_buf; - } + buf = buf_align(buf); ngtcp2_buf_init(&(*pconn)->qlog.buf, buf, NGTCP2_QLOG_BUFLEN); + buf = buf_advance(buf, NGTCP2_QLOG_BUFLEN); } (*pconn)->local.settings = *settings; if (settings->tokenlen) { - buf = ngtcp2_mem_malloc(mem, settings->tokenlen); - if (buf == NULL) { + tokenbuf = ngtcp2_mem_malloc(mem, settings->tokenlen); + if (tokenbuf == NULL) { rv = NGTCP2_ERR_NOMEM; goto fail_token; } - memcpy(buf, settings->token, settings->tokenlen); - (*pconn)->local.settings.token = buf; + memcpy(tokenbuf, settings->token, settings->tokenlen); + (*pconn)->local.settings.token = tokenbuf; } else { (*pconn)->local.settings.token = NULL; } + if (settings->pmtud_probeslen) { + (*pconn)->local.settings.pmtud_probes = buf_align(buf); + buf = ngtcp2_cpymem((uint16_t *)(*pconn)->local.settings.pmtud_probes, + settings->pmtud_probes, + sizeof(settings->pmtud_probes[0]) * + settings->pmtud_probeslen); + } + if (!(*pconn)->local.settings.original_version) { (*pconn)->local.settings.original_version = client_chosen_version; } + ngtcp2_dcid_init(&(*pconn)->dcid.current, 0, dcid, NULL); + ngtcp2_dcid_set_path(&(*pconn)->dcid.current, path); + + rv = ngtcp2_gaptr_push(&(*pconn)->dcid.seqgap, 0, 1); + if (rv != 0) { + goto fail_seqgap_push; + } + conn_reset_conn_stat(*pconn, &(*pconn)->cstat); (*pconn)->cstat.initial_rtt = settings->initial_rtt; - (*pconn)->cstat.max_tx_udp_payload_size = - (*pconn)->local.settings.max_tx_udp_payload_size; ngtcp2_rst_init(&(*pconn)->rst); @@ -1224,13 +1259,10 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, goto fail_hs_pktns_init; } - rv = pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APPLICATION, &(*pconn)->rst, - &(*pconn)->cc, settings->initial_pkt_num, &(*pconn)->log, - &(*pconn)->qlog, &(*pconn)->rtb_entry_objalloc, - &(*pconn)->frc_objalloc, mem); - if (rv != 0) { - goto fail_pktns_init; - } + pktns_init(&(*pconn)->pktns, NGTCP2_PKTNS_ID_APPLICATION, &(*pconn)->rst, + &(*pconn)->cc, settings->initial_pkt_num, &(*pconn)->log, + &(*pconn)->qlog, &(*pconn)->rtb_entry_objalloc, + &(*pconn)->frc_objalloc, mem); scident = ngtcp2_mem_malloc(mem, sizeof(*scident)); if (scident == NULL) { @@ -1249,14 +1281,6 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, scident = NULL; - ngtcp2_dcid_init(&(*pconn)->dcid.current, 0, dcid, NULL); - ngtcp2_dcid_set_path(&(*pconn)->dcid.current, path); - - rv = ngtcp2_gaptr_push(&(*pconn)->dcid.seqgap, 0, 1); - if (rv != 0) { - goto fail_seqgap_push; - } - if (settings->preferred_versionslen) { if (!server && !ngtcp2_is_reserved_version(client_chosen_version)) { for (i = 0; i < settings->preferred_versionslen; ++i) { @@ -1268,12 +1292,9 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, assert(i < settings->preferred_versionslen); } - preferred_versions = ngtcp2_mem_malloc( - mem, sizeof(uint32_t) * settings->preferred_versionslen); - if (preferred_versions == NULL) { - rv = NGTCP2_ERR_NOMEM; - goto fail_preferred_versions; - } + preferred_versions = buf_align(buf); + buf = buf_advance(preferred_versions, sizeof(preferred_versions[0]) * + settings->preferred_versionslen); for (i = 0; i < settings->preferred_versionslen; ++i) { assert(ngtcp2_is_supported_version(settings->preferred_versions[i])); @@ -1304,39 +1325,33 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, ngtcp2_is_supported_version(settings->available_versions[i])); } - rv = available_versions_new(&buf, settings->available_versions, - settings->available_versionslen, mem); - if (rv != 0) { - goto fail_available_versions; - } - - (*pconn)->vneg.available_versions = buf; + (*pconn)->vneg.available_versions = buf_align(buf); (*pconn)->vneg.available_versionslen = sizeof(uint32_t) * settings->available_versionslen; + + buf = available_versions_init((*pconn)->vneg.available_versions, + settings->available_versions, + settings->available_versionslen); } else if (server) { if (settings->preferred_versionslen) { - rv = available_versions_new(&buf, settings->preferred_versions, - settings->preferred_versionslen, mem); - if (rv != 0) { - goto fail_available_versions; - } - - (*pconn)->vneg.available_versions = buf; + (*pconn)->vneg.available_versions = buf_align(buf); (*pconn)->vneg.available_versionslen = sizeof(uint32_t) * settings->preferred_versionslen; + + buf = available_versions_init((*pconn)->vneg.available_versions, + settings->preferred_versions, + settings->preferred_versionslen); } else { (*pconn)->vneg.available_versions = server_default_available_versions; (*pconn)->vneg.available_versionslen = sizeof(server_default_available_versions); } - } else if (!server && !ngtcp2_is_reserved_version(client_chosen_version)) { - rv = available_versions_new(&buf, &client_chosen_version, 1, mem); - if (rv != 0) { - goto fail_available_versions; - } - - (*pconn)->vneg.available_versions = buf; + } else if (!ngtcp2_is_reserved_version(client_chosen_version)) { + (*pconn)->vneg.available_versions = buf_align(buf); (*pconn)->vneg.available_versionslen = sizeof(uint32_t); + + buf = available_versions_init((*pconn)->vneg.available_versions, + &client_chosen_version, 1); } (*pconn)->local.settings.available_versions = NULL; @@ -1377,34 +1392,19 @@ static int conn_new(ngtcp2_conn **pconn, const ngtcp2_cid *dcid, return 0; -fail_available_versions: - ngtcp2_mem_free(mem, (*pconn)->vneg.preferred_versions); -fail_preferred_versions: -fail_seqgap_push: fail_scid_set_insert: ngtcp2_mem_free(mem, scident); fail_scident: - pktns_free(&(*pconn)->pktns, mem); -fail_pktns_init: pktns_del((*pconn)->hs_pktns, mem); fail_hs_pktns_init: pktns_del((*pconn)->in_pktns, mem); fail_in_pktns_init: + ngtcp2_gaptr_free(&(*pconn)->dcid.seqgap); +fail_seqgap_push: ngtcp2_mem_free(mem, (uint8_t *)(*pconn)->local.settings.token); fail_token: - ngtcp2_mem_free(mem, (*pconn)->qlog.buf.begin); -fail_qlog_buf: - ngtcp2_idtr_free(&(*pconn)->remote.uni.idtr); - ngtcp2_idtr_free(&(*pconn)->remote.bidi.idtr); - ngtcp2_map_free(&(*pconn)->strms); - delete_scid(&(*pconn)->scid.set, mem); - ngtcp2_ksl_free(&(*pconn)->scid.set); - ngtcp2_gaptr_free(&(*pconn)->dcid.seqgap); - ngtcp2_objalloc_free(&(*pconn)->strm_objalloc); - ngtcp2_objalloc_free(&(*pconn)->rtb_entry_objalloc); - ngtcp2_objalloc_free(&(*pconn)->frc_objalloc); ngtcp2_mem_free(mem, *pconn); -fail_conn: + return rv; } @@ -1471,8 +1471,8 @@ int ngtcp2_conn_server_new_versioned( * credits are considered. */ static uint64_t conn_fc_credits(ngtcp2_conn *conn, ngtcp2_strm *strm) { - return ngtcp2_min(strm->tx.max_offset - strm->tx.offset, - conn->tx.max_offset - conn->tx.offset); + return ngtcp2_min_uint64(strm->tx.max_offset - strm->tx.offset, + conn->tx.max_offset - conn->tx.offset); } /* @@ -1582,11 +1582,6 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { conn_vneg_crypto_free(conn); - ngtcp2_mem_free(conn->mem, conn->vneg.preferred_versions); - if (conn->vneg.available_versions != server_default_available_versions) { - ngtcp2_mem_free(conn->mem, conn->vneg.available_versions); - } - ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_buf.base); ngtcp2_mem_free(conn->mem, conn->crypto.decrypt_hp_buf.base); ngtcp2_mem_free(conn->mem, (uint8_t *)conn->local.settings.token); @@ -1600,8 +1595,6 @@ void ngtcp2_conn_del(ngtcp2_conn *conn) { pktns_del(conn->hs_pktns, conn->mem); pktns_del(conn->in_pktns, conn->mem); - ngtcp2_mem_free(conn->mem, conn->qlog.buf.begin); - ngtcp2_pmtud_del(conn->pmtud); ngtcp2_pv_del(conn->pv); @@ -1665,8 +1658,8 @@ static int conn_ensure_ack_ranges(ngtcp2_conn *conn, size_t n) { * ACK. */ static ngtcp2_duration conn_compute_ack_delay(ngtcp2_conn *conn) { - return ngtcp2_min(conn->local.transport_params.max_ack_delay, - conn->cstat.smoothed_rtt / 8); + return ngtcp2_min_uint64(conn->local.transport_params.max_ack_delay, + conn->cstat.smoothed_rtt / 8); } int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, @@ -2021,12 +2014,13 @@ static int conn_should_pad_pkt(ngtcp2_conn *conn, uint8_t type, size_t left, return 0; } - if (conn->hs_pktns->crypto.tx.ckm && - (conn->hs_pktns->rtb.probe_pkt_left || - !ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm) || - !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) { - /* If we have something to send in Handshake packet, then add - PADDING in Handshake packet. */ + if ((conn->hs_pktns->crypto.tx.ckm && + (conn->hs_pktns->rtb.probe_pkt_left || + !ngtcp2_strm_streamfrq_empty(&conn->hs_pktns->crypto.strm) || + !ngtcp2_acktr_empty(&conn->hs_pktns->acktr))) || + conn->pktns.crypto.tx.ckm) { + /* If we have something to send in Handshake or 1RTT packet, + then add PADDING in that packet. */ min_payloadlen = NGTCP2_MIN_COALESCED_PAYLOADLEN; } else { return 1; @@ -2195,9 +2189,10 @@ static uint8_t conn_pkt_flags_short(ngtcp2_conn *conn) { /* * conn_write_handshake_pkt writes handshake packet in the buffer - * pointed by |dest| whose length is |destlen|. |type| specifies long - * packet type. It should be either NGTCP2_PKT_INITIAL or - * NGTCP2_PKT_HANDSHAKE_PKT. + * pointed by |dest| whose length is |destlen|. |dgram_offset| is the + * offset in UDP datagram payload where this QUIC packet is positioned + * at. |type| specifies long packet type. It should be either + * NGTCP2_PKT_INITIAL or NGTCP2_PKT_HANDSHAKE_PKT. * * |write_datalen| is the minimum length of application data ready to * send in subsequent 0RTT packet. @@ -2212,8 +2207,9 @@ static uint8_t conn_pkt_flags_short(ngtcp2_conn *conn) { */ static ngtcp2_ssize conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, - size_t destlen, uint8_t type, uint8_t flags, - uint64_t write_datalen, ngtcp2_tstamp ts) { + size_t destlen, size_t dgram_offset, uint8_t type, + uint8_t flags, uint64_t write_datalen, + ngtcp2_tstamp ts) { int rv; ngtcp2_ppe ppe; ngtcp2_pkt_hd hd; @@ -2282,7 +2278,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, hd.tokenlen = conn->local.settings.tokenlen; } - ngtcp2_ppe_init(&ppe, dest, destlen, &cc); + ngtcp2_ppe_init(&ppe, dest, destlen, dgram_offset, &cc); rv = ngtcp2_ppe_encode_hd(&ppe, &hd); if (rv != 0) { @@ -2433,7 +2429,7 @@ conn_write_handshake_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, (rtb_entry_flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING) != 0, require_padding)) { lfr.type = NGTCP2_FRAME_PADDING; - lfr.padding.len = ngtcp2_ppe_padding(&ppe); + lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); } else if (pkt_empty) { return 0; } else { @@ -2602,11 +2598,7 @@ static void conn_discard_pktns(ngtcp2_conn *conn, ngtcp2_pktns **ppktns, ngtcp2_conn_set_loss_detection_timer(conn, ts); } -/* - * conn_discard_initial_state discards state for Initial packet number - * space. - */ -static void conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { +void ngtcp2_conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if (!conn->in_pktns) { return; } @@ -2622,11 +2614,7 @@ static void conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { memset(&conn->vneg.tx, 0, sizeof(conn->vneg.tx)); } -/* - * conn_discard_handshake_state discards state for Handshake packet - * number space. - */ -static void conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { +void ngtcp2_conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts) { if (!conn->hs_pktns) { return; } @@ -2694,7 +2682,7 @@ static ngtcp2_ssize conn_write_handshake_ack_pkts(ngtcp2_conn *conn, res += nwrite; if (!conn->server && nwrite) { - conn_discard_initial_state(conn, ts); + ngtcp2_conn_discard_initial_state(conn, ts); } } @@ -2725,9 +2713,9 @@ static ngtcp2_ssize conn_write_client_initial(ngtcp2_conn *conn, return rv; } - return conn_write_handshake_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, - NGTCP2_WRITE_PKT_FLAG_NONE, early_datalen, - ts); + return conn_write_handshake_pkt( + conn, pi, dest, destlen, 0, NGTCP2_PKT_INITIAL, + NGTCP2_WRITE_PKT_FLAG_NONE, early_datalen, ts); } /* @@ -2807,10 +2795,10 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, conn->hs_pktns->rtb.probe_pkt_left)) { /* Discard Initial state here so that Handshake packet is not padded. */ - conn_discard_initial_state(conn, ts); + ngtcp2_conn_discard_initial_state(conn, ts); } else if (conn->in_pktns) { nwrite = - conn_write_handshake_pkt(conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, + conn_write_handshake_pkt(conn, pi, dest, destlen, 0, NGTCP2_PKT_INITIAL, NGTCP2_WRITE_PKT_FLAG_NONE, write_datalen, ts); if (nwrite < 0) { assert(nwrite != NGTCP2_ERR_NOBUF); @@ -2837,10 +2825,10 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, dest += nwrite; destlen -= (size_t)nwrite; - if (destlen) { - /* We might have already added padding to Initial, but in that - case, we should have destlen == 0 and no Handshake packet - will be written. */ + /* If initial packet size is at least + NGTCP2_MAX_UDP_PAYLOAD_SIZE, no extra padding is needed in a + subsequent packet. */ + if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE) { if (conn->server) { it = ngtcp2_rtb_head(&conn->in_pktns->rtb); if (!ngtcp2_ksl_it_end(&it)) { @@ -2856,8 +2844,9 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, } } - nwrite = conn_write_handshake_pkt( - conn, pi, dest, destlen, NGTCP2_PKT_HANDSHAKE, wflags, write_datalen, ts); + nwrite = + conn_write_handshake_pkt(conn, pi, dest, destlen, (size_t)res, + NGTCP2_PKT_HANDSHAKE, wflags, write_datalen, ts); if (nwrite < 0) { assert(nwrite != NGTCP2_ERR_NOBUF); return nwrite; @@ -2869,7 +2858,7 @@ static ngtcp2_ssize conn_write_handshake_pkts(ngtcp2_conn *conn, /* We don't need to send further Initial packet if we have Handshake key and sent something with it. So discard initial state here. */ - conn_discard_initial_state(conn, ts); + ngtcp2_conn_discard_initial_state(conn, ts); } return res; @@ -3097,7 +3086,8 @@ static int conn_remove_retired_connection_id(ngtcp2_conn *conn, * this endpoint sends. */ static size_t conn_min_short_pktlen(ngtcp2_conn *conn) { - return conn->dcid.current.cid.datalen + NGTCP2_MIN_PKT_EXPANDLEN; + return ngtcp2_max(conn->dcid.current.cid.datalen, conn->oscid.datalen) + + NGTCP2_MIN_PKT_EXPANDLEN; } /* @@ -3155,8 +3145,10 @@ static void conn_reset_ppe_pending(ngtcp2_conn *conn) { /* * conn_write_pkt writes a protected packet in the buffer pointed by - * |dest| whose length if |destlen|. |type| specifies the type of - * packet. It can be NGTCP2_PKT_1RTT or NGTCP2_PKT_0RTT. + * |dest| whose length if |destlen|. |dgram_offset| is the offset in + * UDP datagram payload where this QUIC packet is positioned at. + * |type| specifies the type of packet. It can be NGTCP2_PKT_1RTT or + * NGTCP2_PKT_0RTT. * * This function can send new stream data. In order to send stream * data, specify the underlying stream and parameters to @@ -3183,8 +3175,9 @@ static void conn_reset_ppe_pending(ngtcp2_conn *conn) { */ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, uint8_t *dest, size_t destlen, - ngtcp2_vmsg *vmsg, uint8_t type, - uint8_t flags, ngtcp2_tstamp ts) { + size_t dgram_offset, ngtcp2_vmsg *vmsg, + uint8_t type, uint8_t flags, + ngtcp2_tstamp ts) { int rv = 0; ngtcp2_crypto_cc *cc = &conn->pkt.cc; ngtcp2_ppe *ppe = &conn->pkt.ppe; @@ -3369,7 +3362,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), version, 0); - ngtcp2_ppe_init(ppe, dest, destlen, cc); + ngtcp2_ppe_init(ppe, dest, destlen, dgram_offset, cc); rv = ngtcp2_ppe_encode_hd(ppe, hd); if (rv != 0) { @@ -3944,6 +3937,7 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, vmsg->stream.strm->tx.offset += ndatalen; conn->tx.offset += ndatalen; + vmsg->stream.strm->flags |= NGTCP2_STRM_FLAG_ANY_SENT; if (fin) { ngtcp2_strm_shutdown(vmsg->stream.strm, NGTCP2_STRM_FLAG_SHUT_WR); @@ -4166,10 +4160,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, /* TODO Push STREAM frame back to ngtcp2_strm if there is an error before ngtcp2_rtb_entry is safely created and added. */ - if (require_padding || - /* Making full sized packet will help GSO a bit */ - ngtcp2_ppe_left(ppe) < 10) { - lfr.padding.len = ngtcp2_ppe_padding(ppe); + if (require_padding) { + lfr.padding.len = ngtcp2_ppe_dgram_padding(ppe); } else if (type == NGTCP2_PKT_1RTT) { lfr.padding.len = ngtcp2_ppe_padding_size(ppe, min_pktlen); } else { @@ -4332,7 +4324,7 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( pktns->tx.last_pkt_num + 1, pktns_select_pkt_numlen(pktns), version, 0); - ngtcp2_ppe_init(&ppe, dest, destlen, &cc); + ngtcp2_ppe_init(&ppe, dest, destlen, 0, &cc); rv = ngtcp2_ppe_encode_hd(&ppe, &hd); if (rv != 0) { @@ -4354,14 +4346,16 @@ ngtcp2_ssize ngtcp2_conn_write_single_frame_pkt( } lfr.type = NGTCP2_FRAME_PADDING; - if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) { - lfr.padding.len = ngtcp2_ppe_padding(&ppe); + if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL) { + lfr.padding.len = ngtcp2_ppe_dgram_padding_size(&ppe, destlen); + } else if (flags & NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING) { + lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); } else { switch (fr->type) { case NGTCP2_FRAME_PATH_CHALLENGE: case NGTCP2_FRAME_PATH_RESPONSE: if (!conn->server || destlen >= NGTCP2_MAX_UDP_PAYLOAD_SIZE) { - lfr.padding.len = ngtcp2_ppe_padding(&ppe); + lfr.padding.len = ngtcp2_ppe_dgram_padding(&ppe); } else { lfr.padding.len = 0; } @@ -4522,6 +4516,10 @@ static int conn_retire_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { ngtcp2_frame_chain *nfrc; int rv; + if (ngtcp2_conn_check_retired_dcid_tracked(conn, seq)) { + return 0; + } + rv = ngtcp2_conn_track_retired_dcid_seq(conn, seq); if (rv != 0) { return rv; @@ -4664,7 +4662,9 @@ static int conn_start_pmtud(ngtcp2_conn *conn) { rv = ngtcp2_pmtud_new(&conn->pmtud, conn->dcid.current.max_udp_payload_size, hard_max_udp_payload_size, - conn->pktns.tx.last_pkt_num + 1, conn->mem); + conn->pktns.tx.last_pkt_num + 1, + conn->local.settings.pmtud_probes, + conn->local.settings.pmtud_probeslen, conn->mem); if (rv != 0) { return rv; } @@ -4716,7 +4716,7 @@ static ngtcp2_ssize conn_write_pmtud_probe(ngtcp2_conn *conn, nwrite = ngtcp2_conn_write_single_frame_pkt( conn, pi, dest, probelen, NGTCP2_PKT_1RTT, - NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING, &conn->dcid.current.cid, &lfr, + NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL, &conn->dcid.current.cid, &lfr, NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING | NGTCP2_RTB_ENTRY_FLAG_PTO_ELICITING | NGTCP2_RTB_ENTRY_FLAG_PMTUD_PROBE, @@ -6833,6 +6833,12 @@ static int conn_emit_pending_stream_data(ngtcp2_conn *conn, ngtcp2_strm *strm, return rv; } + /* ngtcp2_conn_shutdown_stream_read from a callback will free + strm->rx.rob. */ + if (!strm->rx.rob) { + return 0; + } + ngtcp2_rob_pop(strm->rx.rob, rx_offset - datalen, datalen); } } @@ -8221,7 +8227,7 @@ static int conn_recv_handshake_done(ngtcp2_conn *conn, ngtcp2_tstamp ts) { conn->pktns.rtb.persistent_congestion_start_ts = ts; - conn_discard_handshake_state(conn, ts); + ngtcp2_conn_discard_handshake_state(conn, ts); assert(conn->remote.transport_params); @@ -8550,13 +8556,13 @@ static int conn_recv_non_probing_pkt_on_new_path(ngtcp2_conn *conn, pv->fallback_pto = pto; } + ngtcp2_dcid_copy(&conn->dcid.current, &dcid); + if (!local_addr_eq || (remote_addr_cmp & (NGTCP2_ADDR_COMPARE_FLAG_ADDR | NGTCP2_ADDR_COMPARE_FLAG_FAMILY))) { conn_reset_congestion_state(conn, ts); } - ngtcp2_dcid_copy(&conn->dcid.current, &dcid); - conn_reset_ecn_validation_state(conn); ngtcp2_conn_stop_pmtud(conn); @@ -9822,7 +9828,7 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, } if (conn->hs_pktns->rx.max_pkt_num != -1) { - conn_discard_initial_state(conn, ts); + ngtcp2_conn_discard_initial_state(conn, ts); } if (!conn_is_tls_handshake_completed(conn)) { @@ -9888,7 +9894,7 @@ static ngtcp2_ssize conn_read_handshake(ngtcp2_conn *conn, return rv; } - conn_discard_handshake_state(conn, ts); + ngtcp2_conn_discard_handshake_state(conn, ts); rv = conn_enqueue_handshake_done(conn); if (rv != 0) { @@ -9936,7 +9942,7 @@ int ngtcp2_conn_read_pkt_versioned(ngtcp2_conn *conn, const ngtcp2_path *path, pktlen); if (pktlen == 0) { - return NGTCP2_ERR_INVALID_ARGUMENT; + return 0; } /* client does not expect a packet from unknown path. */ @@ -10035,13 +10041,12 @@ static int conn_check_pkt_num_exhausted(ngtcp2_conn *conn) { * conn_retransmit_retry_early retransmits 0RTT packet after Retry is * received from server. */ -static ngtcp2_ssize conn_retransmit_retry_early(ngtcp2_conn *conn, - ngtcp2_pkt_info *pi, - uint8_t *dest, size_t destlen, - uint8_t flags, - ngtcp2_tstamp ts) { - return conn_write_pkt(conn, pi, dest, destlen, NULL, NGTCP2_PKT_0RTT, flags, - ts); +static ngtcp2_ssize +conn_retransmit_retry_early(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, + uint8_t *dest, size_t destlen, size_t dgram_offset, + uint8_t flags, ngtcp2_tstamp ts) { + return conn_write_pkt(conn, pi, dest, destlen, dgram_offset, NULL, + NGTCP2_PKT_0RTT, flags, ts); } /* @@ -10137,7 +10142,7 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } } else { nwrite = conn_write_handshake_pkt( - conn, pi, dest, destlen, NGTCP2_PKT_INITIAL, + conn, pi, dest, destlen, 0, NGTCP2_PKT_INITIAL, NGTCP2_WRITE_PKT_FLAG_NONE, write_datalen, ts); if (nwrite < 0) { return nwrite; @@ -10146,7 +10151,7 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (pending_early_datalen) { early_spktlen = conn_retransmit_retry_early( - conn, pi, dest + nwrite, destlen - (size_t)nwrite, + conn, pi, dest + nwrite, destlen - (size_t)nwrite, (size_t)nwrite, nwrite ? NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING : NGTCP2_WRITE_PKT_FLAG_NONE, ts); @@ -10186,8 +10191,9 @@ static ngtcp2_ssize conn_write_handshake(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, if (!conn_is_tls_handshake_completed(conn)) { if (!(conn->flags & NGTCP2_CONN_FLAG_EARLY_DATA_REJECTED)) { - nwrite = conn_retransmit_retry_early(conn, pi, dest, destlen, - NGTCP2_WRITE_PKT_FLAG_NONE, ts); + nwrite = + conn_retransmit_retry_early(conn, pi, dest, destlen, (size_t)res, + NGTCP2_WRITE_PKT_FLAG_NONE, ts); if (nwrite < 0) { return nwrite; } @@ -10363,8 +10369,8 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn, datalen = ngtcp2_vec_len(vmsg->stream.data, vmsg->stream.datacnt); send_stream = conn_retry_early_payloadlen(conn) == 0; if (send_stream) { - write_datalen = ngtcp2_min(datalen + NGTCP2_STREAM_OVERHEAD, - NGTCP2_MIN_COALESCED_PAYLOADLEN); + write_datalen = ngtcp2_min_uint64(datalen + NGTCP2_STREAM_OVERHEAD, + NGTCP2_MIN_COALESCED_PAYLOADLEN); if (vmsg->stream.flags & NGTCP2_WRITE_STREAM_FLAG_MORE) { wflags |= NGTCP2_WRITE_PKT_FLAG_MORE; @@ -10428,8 +10434,8 @@ static ngtcp2_ssize conn_client_write_handshake(ngtcp2_conn *conn, return spktlen; } - early_spktlen = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_0RTT, - wflags, ts); + early_spktlen = conn_write_pkt(conn, pi, dest, destlen, (size_t)spktlen, vmsg, + NGTCP2_PKT_0RTT, wflags, ts); if (early_spktlen < 0) { switch (early_spktlen) { case NGTCP2_ERR_STREAM_DATA_BLOCKED: @@ -10905,7 +10911,7 @@ ngtcp2_tstamp ngtcp2_conn_loss_detection_expiry(ngtcp2_conn *conn) { } ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) { - ngtcp2_tstamp res = UINT64_MAX, t; + ngtcp2_tstamp res = UINT64_MAX; ngtcp2_duration pto = conn_compute_pto(conn, &conn->pktns); ngtcp2_scid *scid; ngtcp2_dcid *dcid; @@ -10922,15 +10928,13 @@ ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) { if (!ngtcp2_pq_empty(&conn->scid.used)) { scid = ngtcp2_struct_of(ngtcp2_pq_top(&conn->scid.used), ngtcp2_scid, pe); if (scid->retired_ts != UINT64_MAX) { - t = scid->retired_ts + pto; - res = ngtcp2_min(res, t); + res = ngtcp2_min_uint64(res, scid->retired_ts + pto); } } if (ngtcp2_ringbuf_len(&conn->dcid.retired.rb)) { dcid = ngtcp2_ringbuf_get(&conn->dcid.retired.rb, 0); - t = dcid->retired_ts + pto; - res = ngtcp2_min(res, t); + res = ngtcp2_min_uint64(res, dcid->retired_ts + pto); } if (conn->dcid.current.cid.datalen) { @@ -10941,15 +10945,13 @@ ngtcp2_tstamp ngtcp2_conn_internal_expiry(ngtcp2_conn *conn) { assert(dcid->cid.datalen); assert(dcid->bound_ts != UINT64_MAX); - t = dcid->bound_ts + 3 * pto; - res = ngtcp2_min(res, t); + res = ngtcp2_min_uint64(res, dcid->bound_ts + 3 * pto); } } if (conn->server && conn->early.ckm && conn->early.discard_started_ts != UINT64_MAX) { - t = conn->early.discard_started_ts + 3 * pto; - res = ngtcp2_min(res, t); + res = ngtcp2_min_uint64(res, conn->early.discard_started_ts + 3 * pto); } return res; @@ -10978,19 +10980,13 @@ static ngtcp2_tstamp conn_handshake_expiry(ngtcp2_conn *conn) { } ngtcp2_tstamp ngtcp2_conn_get_expiry(ngtcp2_conn *conn) { - ngtcp2_tstamp t1 = ngtcp2_conn_loss_detection_expiry(conn); - ngtcp2_tstamp t2 = ngtcp2_conn_ack_delay_expiry(conn); - ngtcp2_tstamp t3 = ngtcp2_conn_internal_expiry(conn); - ngtcp2_tstamp t4 = ngtcp2_conn_lost_pkt_expiry(conn); - ngtcp2_tstamp t5 = conn_keep_alive_expiry(conn); - ngtcp2_tstamp t6 = conn_handshake_expiry(conn); - ngtcp2_tstamp t7 = ngtcp2_conn_get_idle_expiry(conn); - ngtcp2_tstamp res = ngtcp2_min(t1, t2); - res = ngtcp2_min(res, t3); - res = ngtcp2_min(res, t4); - res = ngtcp2_min(res, t5); - res = ngtcp2_min(res, t6); - res = ngtcp2_min(res, t7); + ngtcp2_tstamp res = ngtcp2_min_uint64(ngtcp2_conn_loss_detection_expiry(conn), + ngtcp2_conn_ack_delay_expiry(conn)); + res = ngtcp2_min_uint64(res, ngtcp2_conn_internal_expiry(conn)); + res = ngtcp2_min_uint64(res, ngtcp2_conn_lost_pkt_expiry(conn)); + res = ngtcp2_min_uint64(res, conn_keep_alive_expiry(conn)); + res = ngtcp2_min_uint64(res, conn_handshake_expiry(conn)); + res = ngtcp2_min_uint64(res, ngtcp2_conn_get_idle_expiry(conn)); return ngtcp2_min(res, conn->tx.pacing.next_ts); } @@ -11734,19 +11730,24 @@ ngtcp2_ssize ngtcp2_conn_writev_stream_versioned( return NGTCP2_ERR_INVALID_ARGUMENT; } - if ((uint64_t)datalen > NGTCP2_MAX_VARINT - strm->tx.offset || - (uint64_t)datalen > NGTCP2_MAX_VARINT - conn->tx.offset) { - return NGTCP2_ERR_INVALID_ARGUMENT; - } + if (datalen == 0 && !(flags & NGTCP2_WRITE_STREAM_FLAG_FIN) && + (strm->flags & NGTCP2_STRM_FLAG_ANY_SENT)) { + pvmsg = NULL; + } else { + if ((uint64_t)datalen > NGTCP2_MAX_VARINT - strm->tx.offset || + (uint64_t)datalen > NGTCP2_MAX_VARINT - conn->tx.offset) { + return NGTCP2_ERR_INVALID_ARGUMENT; + } - vmsg.type = NGTCP2_VMSG_TYPE_STREAM; - vmsg.stream.strm = strm; - vmsg.stream.flags = flags; - vmsg.stream.data = datav; - vmsg.stream.datacnt = datavcnt; - vmsg.stream.pdatalen = pdatalen; + vmsg.type = NGTCP2_VMSG_TYPE_STREAM; + vmsg.stream.strm = strm; + vmsg.stream.flags = flags; + vmsg.stream.data = datav; + vmsg.stream.datacnt = datavcnt; + vmsg.stream.pdatalen = pdatalen; - pvmsg = &vmsg; + pvmsg = &vmsg; + } } else { pvmsg = NULL; } @@ -11867,10 +11868,9 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, assert(dest[0] & NGTCP2_HEADER_FORM_BIT); assert(conn->negotiated_version); - if (ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == - NGTCP2_PKT_INITIAL) { - /* We have added padding already, but in that case, there is no - space left to write 1RTT packet. */ + if (nwrite < NGTCP2_MAX_UDP_PAYLOAD_SIZE && + ngtcp2_pkt_get_type_long(conn->negotiated_version, dest[0]) == + NGTCP2_PKT_INITIAL) { wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } @@ -11931,14 +11931,12 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, dest += nwrite; destlen -= (size_t)nwrite; - if (conn->in_pktns && nwrite > 0) { + if (res < NGTCP2_MAX_UDP_PAYLOAD_SIZE && conn->in_pktns && nwrite > 0) { it = ngtcp2_rtb_head(&conn->in_pktns->rtb); if (!ngtcp2_ksl_it_end(&it)) { rtbent = ngtcp2_ksl_it_get(&it); if (rtbent->hd.pkt_num != prev_in_pkt_num && (rtbent->flags & NGTCP2_RTB_ENTRY_FLAG_ACK_ELICITING)) { - /* We have added padding already, but in that case, there - is no space left to write 1RTT packet. */ wflags |= NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING; } } @@ -12004,8 +12002,8 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, } /* dest and destlen have already been adjusted in ppe in the first run. They are adjusted for probe packet later. */ - nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_1RTT, - wflags, ts); + nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg, + NGTCP2_PKT_1RTT, wflags, ts); goto fin; } else { conn->pkt.require_padding = @@ -12100,14 +12098,14 @@ ngtcp2_ssize ngtcp2_conn_write_vmsg(ngtcp2_conn *conn, ngtcp2_path *path, "transmit probe pkt left=%zu", conn->pktns.rtb.probe_pkt_left); - nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_1RTT, - wflags, ts); + nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg, + NGTCP2_PKT_1RTT, wflags, ts); goto fin; } - nwrite = conn_write_pkt(conn, pi, dest, destlen, vmsg, NGTCP2_PKT_1RTT, - wflags, ts); + nwrite = conn_write_pkt(conn, pi, dest, destlen, (size_t)res, vmsg, + NGTCP2_PKT_1RTT, wflags, ts); if (nwrite) { assert(nwrite != NGTCP2_ERR_NOBUF); goto fin; @@ -12326,12 +12324,9 @@ ngtcp2_ssize ngtcp2_conn_write_application_close_pkt( destlen -= (size_t)nwrite; } - if (conn->state != NGTCP2_CS_POST_HANDSHAKE) { - assert(res); - - if (!conn->server || !conn->pktns.crypto.tx.ckm) { - return res; - } + if (conn->state != NGTCP2_CS_POST_HANDSHAKE && + (!conn->server || !conn->pktns.crypto.tx.ckm)) { + return res; } assert(conn->pktns.crypto.tx.ckm); @@ -12393,6 +12388,16 @@ void ngtcp2_ccerr_set_liberr(ngtcp2_ccerr *ccerr, int liberr, reasonlen); return; + case NGTCP2_ERR_DROP_CONN: + ccerr_init(ccerr, NGTCP2_CCERR_TYPE_DROP_CONN, NGTCP2_NO_ERROR, reason, + reasonlen); + + return; + case NGTCP2_ERR_RETRY: + ccerr_init(ccerr, NGTCP2_CCERR_TYPE_RETRY, NGTCP2_NO_ERROR, reason, + reasonlen); + + return; }; ngtcp2_ccerr_set_transport_error( @@ -13597,20 +13602,11 @@ size_t ngtcp2_conn_get_send_quantum(ngtcp2_conn *conn) { } int ngtcp2_conn_track_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { - size_t i; - if (conn->dcid.retire_unacked.len >= ngtcp2_arraylen(conn->dcid.retire_unacked.seqs)) { return NGTCP2_ERR_CONNECTION_ID_LIMIT; } - /* Make sure that we do not have a duplicate */ - for (i = 0; i < conn->dcid.retire_unacked.len; ++i) { - if (conn->dcid.retire_unacked.seqs[i] == seq) { - ngtcp2_unreachable(); - } - } - conn->dcid.retire_unacked.seqs[conn->dcid.retire_unacked.len++] = seq; return 0; @@ -13635,6 +13631,18 @@ void ngtcp2_conn_untrack_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq) { } } +int ngtcp2_conn_check_retired_dcid_tracked(ngtcp2_conn *conn, uint64_t seq) { + size_t i; + + for (i = 0; i < conn->dcid.retire_unacked.len; ++i) { + if (conn->dcid.retire_unacked.seqs[i] == seq) { + return 1; + } + } + + return 0; +} + size_t ngtcp2_conn_get_stream_loss_count(ngtcp2_conn *conn, int64_t stream_id) { ngtcp2_strm *strm = ngtcp2_conn_find_stream(conn, stream_id); @@ -13652,45 +13660,6 @@ void ngtcp2_path_challenge_entry_init(ngtcp2_path_challenge_entry *pcent, memcpy(pcent->data, data, sizeof(pcent->data)); } -void ngtcp2_settings_default_versioned(int settings_version, - ngtcp2_settings *settings) { - (void)settings_version; - - memset(settings, 0, sizeof(*settings)); - settings->cc_algo = NGTCP2_CC_ALGO_CUBIC; - settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT; - settings->ack_thresh = 2; - settings->max_tx_udp_payload_size = 1500 - 48; - settings->handshake_timeout = UINT64_MAX; -} - -void ngtcp2_transport_params_default_versioned( - int transport_params_version, ngtcp2_transport_params *params) { - size_t len; - - switch (transport_params_version) { - case NGTCP2_TRANSPORT_PARAMS_VERSION: - len = sizeof(*params); - - break; - default: - ngtcp2_unreachable(); - } - - memset(params, 0, len); - - switch (transport_params_version) { - case NGTCP2_TRANSPORT_PARAMS_VERSION: - params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; - params->active_connection_id_limit = - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; - params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; - params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; - - break; - } -} - /* The functions prefixed with ngtcp2_pkt_ are usually put inside ngtcp2_pkt.c. This function uses encryption construct and uses test data defined only in ngtcp2_conn_test.c, so it is written @@ -13726,7 +13695,7 @@ ngtcp2_ssize ngtcp2_pkt_write_connection_close( cc.encrypt = encrypt; cc.hp_mask = hp_mask; - ngtcp2_ppe_init(&ppe, dest, destlen, &cc); + ngtcp2_ppe_init(&ppe, dest, destlen, 0, &cc); rv = ngtcp2_ppe_encode_hd(&ppe, &hd); if (rv != 0) { diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h index 4ed6787..1172816 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conn.h @@ -65,9 +65,6 @@ typedef enum { NGTCP2_CS_DRAINING, } ngtcp2_conn_state; -/* NGTCP2_MAX_STREAMS is the maximum number of streams. */ -#define NGTCP2_MAX_STREAMS (1LL << 60) - /* NGTCP2_MAX_NUM_BUFFED_RX_PKTS is the maximum number of buffered reordered packets. */ #define NGTCP2_MAX_NUM_BUFFED_RX_PKTS 4 @@ -121,12 +118,18 @@ typedef enum { /* NGTCP2_WRITE_PKT_FLAG_NONE indicates that no flag is set. */ #define NGTCP2_WRITE_PKT_FLAG_NONE 0x00u /* NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING indicates that packet other - than Initial packet should be padded. Initial packet might be - padded based on QUIC requirement regardless of this flag. */ + than Initial packet should be padded so that UDP datagram payload + is at least NGTCP2_MAX_UDP_PAYLOAD_SIZE bytes. Initial packet + might be padded based on QUIC requirement regardless of this + flag. */ #define NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING 0x01u /* NGTCP2_WRITE_PKT_FLAG_MORE indicates that more frames might come and it should be encoded into the current packet. */ #define NGTCP2_WRITE_PKT_FLAG_MORE 0x02u +/* NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL is just like + NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING, but it requests to add + padding to the full UDP datagram payload size. */ +#define NGTCP2_WRITE_PKT_FLAG_REQUIRE_PADDING_FULL 0x04u /* * ngtcp2_max_frame is defined so that it covers the largest ACK @@ -974,6 +977,12 @@ int ngtcp2_conn_track_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq); void ngtcp2_conn_untrack_retired_dcid_seq(ngtcp2_conn *conn, uint64_t seq); /* + * ngtcp2_conn_check_retired_dcid_tracked returns nonzero if |seq| has + * already been tracked. + */ +int ngtcp2_conn_check_retired_dcid_tracked(ngtcp2_conn *conn, uint64_t seq); + +/* * ngtcp2_conn_server_negotiate_version negotiates QUIC version. It * is compatible version negotiation. It returns the negotiated QUIC * version. This function must not be called by client. @@ -1156,4 +1165,16 @@ int ngtcp2_conn_create_ack_frame(ngtcp2_conn *conn, ngtcp2_frame **pfr, ngtcp2_tstamp ts, ngtcp2_duration ack_delay, uint64_t ack_delay_exponent); +/* + * ngtcp2_conn_discard_initial_state discards state for Initial packet + * number space. + */ +void ngtcp2_conn_discard_initial_state(ngtcp2_conn *conn, ngtcp2_tstamp ts); + +/* + * ngtcp2_conn_discard_handshake_state discards state for Handshake + * packet number space. + */ +void ngtcp2_conn_discard_handshake_state(ngtcp2_conn *conn, ngtcp2_tstamp ts); + #endif /* NGTCP2_CONN_H */ diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c deleted file mode 100644 index eb85687..0000000 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * ngtcp2 - * - * Copyright (c) 2023 ngtcp2 contributors - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ngtcp2_conversion.h" - -#include <string.h> -#include <assert.h> - -static void transport_params_copy(int transport_params_version, - ngtcp2_transport_params *dest, - const ngtcp2_transport_params *src) { - assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); - - switch (transport_params_version) { - case NGTCP2_TRANSPORT_PARAMS_V1: - memcpy(dest, src, - offsetof(ngtcp2_transport_params, version_info_present) + - sizeof(src->version_info_present)); - - break; - } -} - -const ngtcp2_transport_params * -ngtcp2_transport_params_convert_to_latest(ngtcp2_transport_params *dest, - int transport_params_version, - const ngtcp2_transport_params *src) { - if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { - return src; - } - - ngtcp2_transport_params_default(dest); - - transport_params_copy(transport_params_version, dest, src); - - return dest; -} - -void ngtcp2_transport_params_convert_to_old( - int transport_params_version, ngtcp2_transport_params *dest, - const ngtcp2_transport_params *src) { - assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); - - transport_params_copy(transport_params_version, dest, src); -} diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c index 0a3ecf6..9f61791 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.c @@ -27,11 +27,7 @@ #include <string.h> #include <assert.h> -#include "ngtcp2_str.h" -#include "ngtcp2_conv.h" -#include "ngtcp2_conn.h" #include "ngtcp2_net.h" -#include "ngtcp2_conversion.h" int ngtcp2_crypto_km_new(ngtcp2_crypto_km **pckm, const uint8_t *secret, size_t secretlen, @@ -85,6 +81,16 @@ void ngtcp2_crypto_km_del(ngtcp2_crypto_km *ckm, const ngtcp2_mem *mem) { return; } + if (ckm->secret.len) { +#ifdef WIN32 + SecureZeroMemory(ckm->secret.base, ckm->secret.len); +#elif defined(HAVE_EXPLICIT_BZERO) + explicit_bzero(ckm->secret.base, ckm->secret.len); +#elif defined(HAVE_MEMSET_S) + memset_s(ckm->secret.base, ckm->secret.len, 0, ckm->secret.len); +#endif /* HAVE_MEMSET_S */ + } + ngtcp2_mem_free(mem, ckm); } @@ -102,808 +108,3 @@ void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen, dest[ivlen - 8 + i] ^= ((uint8_t *)&n)[i]; } } - -/* - * varint_paramlen returns the length of a single transport parameter - * which has variable integer in its parameter. - */ -static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) { - size_t valuelen = ngtcp2_put_uvarintlen(param); - return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(valuelen) + valuelen; -} - -/* - * write_varint_param writes parameter |id| of the given |value| in - * varint encoding. It returns p + the number of bytes written. - */ -static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id, - uint64_t value) { - p = ngtcp2_put_uvarint(p, id); - p = ngtcp2_put_uvarint(p, ngtcp2_put_uvarintlen(value)); - return ngtcp2_put_uvarint(p, value); -} - -/* - * zero_paramlen returns the length of a single transport parameter - * which has zero length value in its parameter. - */ -static size_t zero_paramlen(ngtcp2_transport_param_id id) { - return ngtcp2_put_uvarintlen(id) + 1; -} - -/* - * write_zero_param writes parameter |id| that has zero length value. - * It returns p + the number of bytes written. - */ -static uint8_t *write_zero_param(uint8_t *p, ngtcp2_transport_param_id id) { - p = ngtcp2_put_uvarint(p, id); - *p++ = 0; - - return p; -} - -/* - * cid_paramlen returns the length of a single transport parameter - * which has |cid| as value. - */ -static size_t cid_paramlen(ngtcp2_transport_param_id id, - const ngtcp2_cid *cid) { - return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(cid->datalen) + - cid->datalen; -} - -/* - * write_cid_param writes parameter |id| of the given |cid|. It - * returns p + the number of bytes written. - */ -static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id, - const ngtcp2_cid *cid) { - assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN); - assert(cid->datalen <= NGTCP2_MAX_CIDLEN); - - p = ngtcp2_put_uvarint(p, id); - p = ngtcp2_put_uvarint(p, cid->datalen); - if (cid->datalen) { - p = ngtcp2_cpymem(p, cid->data, cid->datalen); - } - return p; -} - -static const uint8_t empty_address[16]; - -ngtcp2_ssize ngtcp2_transport_params_encode_versioned( - uint8_t *dest, size_t destlen, int transport_params_version, - const ngtcp2_transport_params *params) { - uint8_t *p; - size_t len = 0; - /* For some reason, gcc 7.3.0 requires this initialization. */ - size_t preferred_addrlen = 0; - size_t version_infolen = 0; - const ngtcp2_sockaddr_in *sa_in; - const ngtcp2_sockaddr_in6 *sa_in6; - ngtcp2_transport_params paramsbuf; - - params = ngtcp2_transport_params_convert_to_latest( - ¶msbuf, transport_params_version, params); - - if (params->original_dcid_present) { - len += - cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, - ¶ms->original_dcid); - } - - if (params->stateless_reset_token_present) { - len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) + - ngtcp2_put_uvarintlen(NGTCP2_STATELESS_RESET_TOKENLEN) + - NGTCP2_STATELESS_RESET_TOKENLEN; - } - - if (params->preferred_addr_present) { - assert(params->preferred_addr.cid.datalen >= NGTCP2_MIN_CIDLEN); - assert(params->preferred_addr.cid.datalen <= NGTCP2_MAX_CIDLEN); - preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ + - 16 /* ipv6Address */ + 2 /* ipv6Port */ - + 1 + params->preferred_addr.cid.datalen /* CID */ + - NGTCP2_STATELESS_RESET_TOKENLEN; - len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) + - ngtcp2_put_uvarintlen(preferred_addrlen) + preferred_addrlen; - } - if (params->retry_scid_present) { - len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, - ¶ms->retry_scid); - } - - if (params->initial_scid_present) { - len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, - ¶ms->initial_scid); - } - - if (params->initial_max_stream_data_bidi_local) { - len += varint_paramlen( - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, - params->initial_max_stream_data_bidi_local); - } - if (params->initial_max_stream_data_bidi_remote) { - len += varint_paramlen( - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, - params->initial_max_stream_data_bidi_remote); - } - if (params->initial_max_stream_data_uni) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI, - params->initial_max_stream_data_uni); - } - if (params->initial_max_data) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA, - params->initial_max_data); - } - if (params->initial_max_streams_bidi) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI, - params->initial_max_streams_bidi); - } - if (params->initial_max_streams_uni) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI, - params->initial_max_streams_uni); - } - if (params->max_udp_payload_size != - NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, - params->max_udp_payload_size); - } - if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT, - params->ack_delay_exponent); - } - if (params->disable_active_migration) { - len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); - } - if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, - params->max_ack_delay / NGTCP2_MILLISECONDS); - } - if (params->max_idle_timeout) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT, - params->max_idle_timeout / NGTCP2_MILLISECONDS); - } - if (params->active_connection_id_limit && - params->active_connection_id_limit != - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT, - params->active_connection_id_limit); - } - if (params->max_datagram_frame_size) { - len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE, - params->max_datagram_frame_size); - } - if (params->grease_quic_bit) { - len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); - } - if (params->version_info_present) { - version_infolen = - sizeof(uint32_t) + params->version_info.available_versionslen; - len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION) + - ngtcp2_put_uvarintlen(version_infolen) + version_infolen; - } - - if (dest == NULL && destlen == 0) { - return (ngtcp2_ssize)len; - } - - if (destlen < len) { - return NGTCP2_ERR_NOBUF; - } - - p = dest; - - if (params->original_dcid_present) { - p = write_cid_param( - p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, - ¶ms->original_dcid); - } - - if (params->stateless_reset_token_present) { - p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN); - p = ngtcp2_put_uvarint(p, sizeof(params->stateless_reset_token)); - p = ngtcp2_cpymem(p, params->stateless_reset_token, - sizeof(params->stateless_reset_token)); - } - - if (params->preferred_addr_present) { - p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS); - p = ngtcp2_put_uvarint(p, preferred_addrlen); - - if (params->preferred_addr.ipv4_present) { - sa_in = ¶ms->preferred_addr.ipv4; - p = ngtcp2_cpymem(p, &sa_in->sin_addr, sizeof(sa_in->sin_addr)); - p = ngtcp2_put_uint16(p, sa_in->sin_port); - } else { - p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in->sin_addr)); - p = ngtcp2_put_uint16(p, 0); - } - - if (params->preferred_addr.ipv6_present) { - sa_in6 = ¶ms->preferred_addr.ipv6; - p = ngtcp2_cpymem(p, &sa_in6->sin6_addr, sizeof(sa_in6->sin6_addr)); - p = ngtcp2_put_uint16(p, sa_in6->sin6_port); - } else { - p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in6->sin6_addr)); - p = ngtcp2_put_uint16(p, 0); - } - - *p++ = (uint8_t)params->preferred_addr.cid.datalen; - if (params->preferred_addr.cid.datalen) { - p = ngtcp2_cpymem(p, params->preferred_addr.cid.data, - params->preferred_addr.cid.datalen); - } - p = ngtcp2_cpymem(p, params->preferred_addr.stateless_reset_token, - sizeof(params->preferred_addr.stateless_reset_token)); - } - - if (params->retry_scid_present) { - p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, - ¶ms->retry_scid); - } - - if (params->initial_scid_present) { - p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, - ¶ms->initial_scid); - } - - if (params->initial_max_stream_data_bidi_local) { - p = write_varint_param( - p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, - params->initial_max_stream_data_bidi_local); - } - - if (params->initial_max_stream_data_bidi_remote) { - p = write_varint_param( - p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, - params->initial_max_stream_data_bidi_remote); - } - - if (params->initial_max_stream_data_uni) { - p = write_varint_param(p, - NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI, - params->initial_max_stream_data_uni); - } - - if (params->initial_max_data) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA, - params->initial_max_data); - } - - if (params->initial_max_streams_bidi) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI, - params->initial_max_streams_bidi); - } - - if (params->initial_max_streams_uni) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI, - params->initial_max_streams_uni); - } - - if (params->max_udp_payload_size != - NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, - params->max_udp_payload_size); - } - - if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT, - params->ack_delay_exponent); - } - - if (params->disable_active_migration) { - p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); - } - - if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, - params->max_ack_delay / NGTCP2_MILLISECONDS); - } - - if (params->max_idle_timeout) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT, - params->max_idle_timeout / NGTCP2_MILLISECONDS); - } - - if (params->active_connection_id_limit && - params->active_connection_id_limit != - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT, - params->active_connection_id_limit); - } - - if (params->max_datagram_frame_size) { - p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE, - params->max_datagram_frame_size); - } - - if (params->grease_quic_bit) { - p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); - } - - if (params->version_info_present) { - p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION); - p = ngtcp2_put_uvarint(p, version_infolen); - p = ngtcp2_put_uint32be(p, params->version_info.chosen_version); - if (params->version_info.available_versionslen) { - p = ngtcp2_cpymem(p, params->version_info.available_versions, - params->version_info.available_versionslen); - } - } - - assert((size_t)(p - dest) == len); - - return (ngtcp2_ssize)len; -} - -/* - * decode_varint decodes a single varint from the buffer pointed by - * |*pp| of length |end - *pp|. If it decodes an integer - * successfully, it stores the integer in |*pdest|, increment |*pp| by - * the number of bytes read from |*pp|, and returns 0. Otherwise it - * returns -1. - */ -static int decode_varint(uint64_t *pdest, const uint8_t **pp, - const uint8_t *end) { - const uint8_t *p = *pp; - size_t len; - - if (p == end) { - return -1; - } - - len = ngtcp2_get_uvarintlen(p); - if ((uint64_t)(end - p) < len) { - return -1; - } - - *pp = ngtcp2_get_uvarint(pdest, p); - - return 0; -} - -/* - * decode_varint_param decodes length prefixed value from the buffer - * pointed by |*pp| of length |end - *pp|. The length and value are - * encoded in varint form. If it decodes a value successfully, it - * stores the value in |*pdest|, increment |*pp| by the number of - * bytes read from |*pp|, and returns 0. Otherwise it returns -1. - */ -static int decode_varint_param(uint64_t *pdest, const uint8_t **pp, - const uint8_t *end) { - const uint8_t *p = *pp; - uint64_t valuelen; - - if (decode_varint(&valuelen, &p, end) != 0) { - return -1; - } - - if (p == end) { - return -1; - } - - if ((uint64_t)(end - p) < valuelen) { - return -1; - } - - if (ngtcp2_get_uvarintlen(p) != valuelen) { - return -1; - } - - *pp = ngtcp2_get_uvarint(pdest, p); - - return 0; -} - -/* - * decode_zero_param decodes zero length value from the buffer pointed - * by |*pp| of length |end - *pp|. The length is encoded in varint - * form. If it decodes zero length value successfully, it increments - * |*pp| by 1, and returns 0. Otherwise it returns -1. - */ -static int decode_zero_param(const uint8_t **pp, const uint8_t *end) { - if (*pp == end || **pp != 0) { - return -1; - } - - ++*pp; - - return 0; -} - -/* - * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer - * pointed by |*pp| of length |end - *pp|. The length is encoded in - * varint form. If it decodes a value successfully, it stores the - * value in |*pdest|, increment |*pp| by the number of read from - * |*pp|, and returns the number of bytes read. Otherwise it returns - * the one of the negative error code: - * - * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM - * Could not decode Connection ID. - */ -static int decode_cid_param(ngtcp2_cid *pdest, const uint8_t **pp, - const uint8_t *end) { - const uint8_t *p = *pp; - uint64_t valuelen; - - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) || - valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - ngtcp2_cid_init(pdest, p, (size_t)valuelen); - - p += valuelen; - - *pp = p; - - return 0; -} - -int ngtcp2_transport_params_decode_versioned(int transport_params_version, - ngtcp2_transport_params *dest, - const uint8_t *data, - size_t datalen) { - const uint8_t *p, *end, *lend; - size_t len; - uint64_t param_type; - uint64_t valuelen; - int rv; - ngtcp2_sockaddr_in *sa_in; - ngtcp2_sockaddr_in6 *sa_in6; - uint32_t version; - ngtcp2_transport_params *params, paramsbuf; - - if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { - params = dest; - } else { - params = ¶msbuf; - } - - /* Set default values */ - memset(params, 0, sizeof(*params)); - params->original_dcid_present = 0; - params->initial_scid_present = 0; - params->initial_max_streams_bidi = 0; - params->initial_max_streams_uni = 0; - params->initial_max_stream_data_bidi_local = 0; - params->initial_max_stream_data_bidi_remote = 0; - params->initial_max_stream_data_uni = 0; - params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; - params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; - params->stateless_reset_token_present = 0; - params->preferred_addr_present = 0; - params->disable_active_migration = 0; - params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; - params->max_idle_timeout = 0; - params->active_connection_id_limit = - NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; - params->retry_scid_present = 0; - params->max_datagram_frame_size = 0; - memset(¶ms->retry_scid, 0, sizeof(params->retry_scid)); - memset(¶ms->initial_scid, 0, sizeof(params->initial_scid)); - memset(¶ms->original_dcid, 0, sizeof(params->original_dcid)); - params->version_info_present = 0; - - p = data; - end = data + datalen; - - for (; (size_t)(end - p) >= 2;) { - if (decode_varint(¶m_type, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - switch (param_type) { - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL: - if (decode_varint_param(¶ms->initial_max_stream_data_bidi_local, &p, - end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE: - if (decode_varint_param(¶ms->initial_max_stream_data_bidi_remote, &p, - end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI: - if (decode_varint_param(¶ms->initial_max_stream_data_uni, &p, end) != - 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA: - if (decode_varint_param(¶ms->initial_max_data, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI: - if (decode_varint_param(¶ms->initial_max_streams_bidi, &p, end) != - 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI: - if (decode_varint_param(¶ms->initial_max_streams_uni, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT: - if (decode_varint_param(¶ms->max_idle_timeout, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - params->max_idle_timeout *= NGTCP2_MILLISECONDS; - break; - case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE: - if (decode_varint_param(¶ms->max_udp_payload_size, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN: - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)valuelen != sizeof(params->stateless_reset_token)) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - p = ngtcp2_get_bytes(params->stateless_reset_token, p, - sizeof(params->stateless_reset_token)); - params->stateless_reset_token_present = 1; - - break; - case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT: - if (decode_varint_param(¶ms->ack_delay_exponent, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->ack_delay_exponent > 20) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS: - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)(end - p) < valuelen) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ + - 2 /* ipv6Port */ - + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN; - if (valuelen < len) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - sa_in = ¶ms->preferred_addr.ipv4; - - p = ngtcp2_get_bytes(&sa_in->sin_addr, p, sizeof(sa_in->sin_addr)); - p = ngtcp2_get_uint16be(&sa_in->sin_port, p); - - if (sa_in->sin_port || memcmp(empty_address, &sa_in->sin_addr, - sizeof(sa_in->sin_addr)) != 0) { - sa_in->sin_family = NGTCP2_AF_INET; - params->preferred_addr.ipv4_present = 1; - } - - sa_in6 = ¶ms->preferred_addr.ipv6; - - p = ngtcp2_get_bytes(&sa_in6->sin6_addr, p, sizeof(sa_in6->sin6_addr)); - p = ngtcp2_get_uint16be(&sa_in6->sin6_port, p); - - if (sa_in6->sin6_port || memcmp(empty_address, &sa_in6->sin6_addr, - sizeof(sa_in6->sin6_addr)) != 0) { - sa_in6->sin6_family = NGTCP2_AF_INET6; - params->preferred_addr.ipv6_present = 1; - } - - /* cid */ - params->preferred_addr.cid.datalen = *p++; - len += params->preferred_addr.cid.datalen; - if (valuelen != len || - params->preferred_addr.cid.datalen > NGTCP2_MAX_CIDLEN || - params->preferred_addr.cid.datalen < NGTCP2_MIN_CIDLEN) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->preferred_addr.cid.datalen) { - p = ngtcp2_get_bytes(params->preferred_addr.cid.data, p, - params->preferred_addr.cid.datalen); - } - - /* stateless reset token */ - p = ngtcp2_get_bytes( - params->preferred_addr.stateless_reset_token, p, - sizeof(params->preferred_addr.stateless_reset_token)); - params->preferred_addr_present = 1; - break; - case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION: - if (decode_zero_param(&p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - params->disable_active_migration = 1; - break; - case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID: - rv = decode_cid_param(¶ms->original_dcid, &p, end); - if (rv != 0) { - return rv; - } - params->original_dcid_present = 1; - break; - case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID: - rv = decode_cid_param(¶ms->retry_scid, &p, end); - if (rv != 0) { - return rv; - } - params->retry_scid_present = 1; - break; - case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID: - rv = decode_cid_param(¶ms->initial_scid, &p, end); - if (rv != 0) { - return rv; - } - params->initial_scid_present = 1; - break; - case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY: - if (decode_varint_param(¶ms->max_ack_delay, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (params->max_ack_delay >= 16384) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - params->max_ack_delay *= NGTCP2_MILLISECONDS; - break; - case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT: - if (decode_varint_param(¶ms->active_connection_id_limit, &p, end) != - 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE: - if (decode_varint_param(¶ms->max_datagram_frame_size, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - break; - case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT: - if (decode_zero_param(&p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - params->grease_quic_bit = 1; - break; - case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION: - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)(end - p) < valuelen) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (valuelen < sizeof(uint32_t) || (valuelen & 0x3)) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - p = ngtcp2_get_uint32(¶ms->version_info.chosen_version, p); - if (params->version_info.chosen_version == 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (valuelen > sizeof(uint32_t)) { - params->version_info.available_versions = (uint8_t *)p; - params->version_info.available_versionslen = - (size_t)valuelen - sizeof(uint32_t); - - for (lend = p + (valuelen - sizeof(uint32_t)); p != lend;) { - p = ngtcp2_get_uint32(&version, p); - if (version == 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - } - } - params->version_info_present = 1; - break; - default: - /* Ignore unknown parameter */ - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if ((size_t)(end - p) < valuelen) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - p += valuelen; - break; - } - } - - if (end - p != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - - if (transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION) { - ngtcp2_transport_params_convert_to_old(transport_params_version, dest, - params); - } - - return 0; -} - -static int transport_params_copy_new(ngtcp2_transport_params **pdest, - const ngtcp2_transport_params *src, - const ngtcp2_mem *mem) { - size_t len = sizeof(**pdest); - ngtcp2_transport_params *dest; - uint8_t *p; - - if (src->version_info_present) { - len += src->version_info.available_versionslen; - } - - dest = ngtcp2_mem_malloc(mem, len); - if (dest == NULL) { - return NGTCP2_ERR_NOMEM; - } - - *dest = *src; - - if (src->version_info_present && src->version_info.available_versionslen) { - p = (uint8_t *)dest + sizeof(*dest); - memcpy(p, src->version_info.available_versions, - src->version_info.available_versionslen); - dest->version_info.available_versions = p; - } - - *pdest = dest; - - return 0; -} - -int ngtcp2_transport_params_decode_new(ngtcp2_transport_params **pparams, - const uint8_t *data, size_t datalen, - const ngtcp2_mem *mem) { - int rv; - ngtcp2_transport_params params; - - rv = ngtcp2_transport_params_decode(¶ms, data, datalen); - if (rv < 0) { - return rv; - } - - if (mem == NULL) { - mem = ngtcp2_mem_default(); - } - - return transport_params_copy_new(pparams, ¶ms, mem); -} - -void ngtcp2_transport_params_del(ngtcp2_transport_params *params, - const ngtcp2_mem *mem) { - if (params == NULL) { - return; - } - - if (mem == NULL) { - mem = ngtcp2_mem_default(); - } - - ngtcp2_mem_free(mem, params); -} - -int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest, - const ngtcp2_transport_params *src, - const ngtcp2_mem *mem) { - if (src == NULL) { - *pdest = NULL; - return 0; - } - - return transport_params_copy_new(pdest, src, mem); -} diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h index b78429b..c561723 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_crypto.h @@ -41,33 +41,6 @@ /* NGTCP2_MAX_AEAD_OVERHEAD is expected maximum AEAD overhead. */ #define NGTCP2_MAX_AEAD_OVERHEAD 16 -/* ngtcp2_transport_param_id is the registry of QUIC transport - parameter ID. */ -typedef uint64_t ngtcp2_transport_param_id; - -#define NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID 0x00 -#define NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT 0x01 -#define NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN 0x02 -#define NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE 0x03 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA 0x04 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL 0x05 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE 0x06 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI 0x07 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI 0x08 -#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI 0x09 -#define NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT 0x0a -#define NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY 0x0b -#define NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION 0x0c -#define NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS 0x0d -#define NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT 0x0e -#define NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID 0x0f -#define NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID 0x10 -/* https://datatracker.ietf.org/doc/html/rfc9221 */ -#define NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE 0x20 -#define NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT 0x2ab2 -/* https://datatracker.ietf.org/doc/html/rfc9368 */ -#define NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION 0x11 - /* NGTCP2_CRYPTO_KM_FLAG_NONE indicates that no flag is set. */ #define NGTCP2_CRYPTO_KM_FLAG_NONE 0x00u /* NGTCP2_CRYPTO_KM_FLAG_KEY_PHASE_ONE is set if key phase bit is @@ -127,21 +100,4 @@ typedef struct ngtcp2_crypto_cc { void ngtcp2_crypto_create_nonce(uint8_t *dest, const uint8_t *iv, size_t ivlen, int64_t pkt_num); -/* - * ngtcp2_transport_params_copy_new makes a copy of |src|, and assigns - * it to |*pdest|. If |src| is NULL, NULL is assigned to |*pdest|. - * - * Caller is responsible to call ngtcp2_transport_params_del to free - * the memory assigned to |*pdest|. - * - * This function returns 0 if it succeeds, or one of the following - * negative error codes: - * - * NGTCP2_ERR_NOMEM - * Out of memory. - */ -int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest, - const ngtcp2_transport_params *src, - const ngtcp2_mem *mem); - #endif /* NGTCP2_CRYPTO_H */ diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_macro.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_macro.h index 28d3461..8974c86 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_macro.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_macro.h @@ -55,4 +55,40 @@ */ #define ngtcp2_arraylen(A) (sizeof(A) / sizeof(A[0])) +/* + * ngtcp2_max variants but they are inline functions. The + * intermediate values are stored in parameters so that they are + * evaluated just once. + */ +#define ngtcp2_max_def(SUFFIX, T) \ + static inline T ngtcp2_max_##SUFFIX(T a, T b) { return a < b ? b : a; } + +ngtcp2_max_def(int8, int8_t); +ngtcp2_max_def(int16, int16_t); +ngtcp2_max_def(int32, int32_t); +ngtcp2_max_def(int64, int64_t); +ngtcp2_max_def(uint8, uint8_t); +ngtcp2_max_def(uint16, uint16_t); +ngtcp2_max_def(uint32, uint32_t); +ngtcp2_max_def(uint64, uint64_t); +ngtcp2_max_def(size, size_t); + +/* + * ngtcp2_min variants but they are inline functions. The + * intermediate values are stored in parameters so that they are + * evaluated just once. + */ +#define ngtcp2_min_def(SUFFIX, T) \ + static inline T ngtcp2_min_##SUFFIX(T a, T b) { return a < b ? a : b; } + +ngtcp2_min_def(int8, int8_t); +ngtcp2_min_def(int16, int16_t); +ngtcp2_min_def(int32, int32_t); +ngtcp2_min_def(int64, int64_t); +ngtcp2_min_def(uint8, uint8_t); +ngtcp2_min_def(uint16, uint16_t); +ngtcp2_min_def(uint32, uint32_t); +ngtcp2_min_def(uint64, uint64_t); +ngtcp2_min_def(size, size_t); + #endif /* NGTCP2_MACRO_H */ diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c index 1687ff2..f4ceb32 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.c @@ -2208,7 +2208,7 @@ ngtcp2_pkt_write_stateless_reset(uint8_t *dest, size_t destlen, p = dest; - randlen = ngtcp2_min(destlen - NGTCP2_STATELESS_RESET_TOKENLEN, randlen); + randlen = ngtcp2_min_size(destlen - NGTCP2_STATELESS_RESET_TOKENLEN, randlen); p = ngtcp2_cpymem(p, rand, randlen); p = ngtcp2_cpymem(p, stateless_reset_token, NGTCP2_STATELESS_RESET_TOKENLEN); @@ -2384,21 +2384,21 @@ size_t ngtcp2_pkt_stream_max_datalen(int64_t stream_id, uint64_t offset, #if SIZE_MAX > UINT32_MAX len = ngtcp2_min(len, 4611686018427387903lu); #endif /* SIZE_MAX > UINT32_MAX */ - return (size_t)ngtcp2_min(len, (uint64_t)(left - 8)); + return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 8)); } if (left > 4 + 16383 && len > 16383) { len = ngtcp2_min(len, 1073741823); - return (size_t)ngtcp2_min(len, (uint64_t)(left - 4)); + return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 4)); } if (left > 2 + 63 && len > 63) { len = ngtcp2_min(len, 16383); - return (size_t)ngtcp2_min(len, (uint64_t)(left - 2)); + return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 2)); } len = ngtcp2_min(len, 63); - return (size_t)ngtcp2_min(len, (uint64_t)(left - 1)); + return (size_t)ngtcp2_min_uint64(len, (uint64_t)(left - 1)); } size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) { @@ -2416,21 +2416,21 @@ size_t ngtcp2_pkt_crypto_max_datalen(uint64_t offset, size_t len, size_t left) { #if SIZE_MAX > UINT32_MAX len = ngtcp2_min(len, 4611686018427387903lu); #endif /* SIZE_MAX > UINT32_MAX */ - return ngtcp2_min(len, left - 8); + return ngtcp2_min_size(len, left - 8); } if (left > 4 + 16383 && len > 16383) { len = ngtcp2_min(len, 1073741823); - return ngtcp2_min(len, left - 4); + return ngtcp2_min_size(len, left - 4); } if (left > 2 + 63 && len > 63) { len = ngtcp2_min(len, 16383); - return ngtcp2_min(len, left - 2); + return ngtcp2_min_size(len, left - 2); } len = ngtcp2_min(len, 63); - return ngtcp2_min(len, left - 1); + return ngtcp2_min_size(len, left - 1); } size_t ngtcp2_pkt_datagram_framelen(size_t len) { diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h index feec4d3..5f2e448 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pkt.h @@ -95,9 +95,8 @@ /* NGTCP2_MAX_PKT_NUM is the maximum packet number. */ #define NGTCP2_MAX_PKT_NUM ((int64_t)((1ll << 62) - 1)) -/* NGTCP2_MIN_PKT_EXPANDLEN is the minimum packet size expansion in - addition to the minimum DCID length to hide/trigger Stateless - Reset. */ +/* NGTCP2_MIN_PKT_EXPANDLEN is the minimum packet size expansion to + hide/trigger Stateless Reset. */ #define NGTCP2_MIN_PKT_EXPANDLEN 22 /* NGTCP2_RETRY_TAGLEN is the length of Retry packet integrity tag. */ diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.c index 771ef5e..6010e42 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.c @@ -33,7 +33,7 @@ for each probe. */ #define NGTCP2_PMTUD_PROBE_NUM_MAX 3 -static size_t mtu_probes[] = { +static uint16_t pmtud_default_probes[] = { 1454 - 48, /* The well known MTU used by a domestic optic fiber service in Japan. */ 1390 - 48, /* Typical Tunneled MTU */ @@ -41,10 +41,9 @@ static size_t mtu_probes[] = { 1492 - 48, /* PPPoE */ }; -#define NGTCP2_MTU_PROBESLEN ngtcp2_arraylen(mtu_probes) - int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size, size_t hard_max_udp_payload_size, int64_t tx_pkt_num, + const uint16_t *probes, size_t probeslen, const ngtcp2_mem *mem) { ngtcp2_pmtud *pmtud = ngtcp2_mem_malloc(mem, sizeof(ngtcp2_pmtud)); @@ -61,11 +60,19 @@ int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size, pmtud->hard_max_udp_payload_size = hard_max_udp_payload_size; pmtud->min_fail_udp_payload_size = SIZE_MAX; - for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) { - if (mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { + if (probeslen) { + pmtud->probes = probes; + pmtud->probeslen = probeslen; + } else { + pmtud->probes = pmtud_default_probes; + pmtud->probeslen = ngtcp2_arraylen(pmtud_default_probes); + } + + for (; pmtud->mtu_idx < pmtud->probeslen; ++pmtud->mtu_idx) { + if (pmtud->probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { continue; } - if (mtu_probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { + if (pmtud->probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { break; } } @@ -84,9 +91,9 @@ void ngtcp2_pmtud_del(ngtcp2_pmtud *pmtud) { } size_t ngtcp2_pmtud_probelen(ngtcp2_pmtud *pmtud) { - assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN); + assert(pmtud->mtu_idx < pmtud->probeslen); - return mtu_probes[pmtud->mtu_idx]; + return pmtud->probes[pmtud->mtu_idx]; } void ngtcp2_pmtud_probe_sent(ngtcp2_pmtud *pmtud, ngtcp2_duration pto, @@ -107,19 +114,19 @@ int ngtcp2_pmtud_require_probe(ngtcp2_pmtud *pmtud) { } static void pmtud_next_probe(ngtcp2_pmtud *pmtud) { - assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN); + assert(pmtud->mtu_idx < pmtud->probeslen); ++pmtud->mtu_idx; pmtud->num_pkts_sent = 0; pmtud->expiry = UINT64_MAX; - for (; pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN; ++pmtud->mtu_idx) { - if (mtu_probes[pmtud->mtu_idx] <= pmtud->max_udp_payload_size || - mtu_probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { + for (; pmtud->mtu_idx < pmtud->probeslen; ++pmtud->mtu_idx) { + if (pmtud->probes[pmtud->mtu_idx] <= pmtud->max_udp_payload_size || + pmtud->probes[pmtud->mtu_idx] > pmtud->hard_max_udp_payload_size) { continue; } - if (mtu_probes[pmtud->mtu_idx] < pmtud->min_fail_udp_payload_size) { + if (pmtud->probes[pmtud->mtu_idx] < pmtud->min_fail_udp_payload_size) { break; } } @@ -129,9 +136,9 @@ void ngtcp2_pmtud_probe_success(ngtcp2_pmtud *pmtud, size_t payloadlen) { pmtud->max_udp_payload_size = ngtcp2_max(pmtud->max_udp_payload_size, payloadlen); - assert(pmtud->mtu_idx < NGTCP2_MTU_PROBESLEN); + assert(pmtud->mtu_idx < pmtud->probeslen); - if (mtu_probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { + if (pmtud->probes[pmtud->mtu_idx] > pmtud->max_udp_payload_size) { return; } @@ -149,12 +156,12 @@ void ngtcp2_pmtud_handle_expiry(ngtcp2_pmtud *pmtud, ngtcp2_tstamp ts) { return; } - pmtud->min_fail_udp_payload_size = - ngtcp2_min(pmtud->min_fail_udp_payload_size, mtu_probes[pmtud->mtu_idx]); + pmtud->min_fail_udp_payload_size = ngtcp2_min_size( + pmtud->min_fail_udp_payload_size, pmtud->probes[pmtud->mtu_idx]); pmtud_next_probe(pmtud); } int ngtcp2_pmtud_finished(ngtcp2_pmtud *pmtud) { - return pmtud->mtu_idx >= NGTCP2_MTU_PROBESLEN; + return pmtud->mtu_idx >= pmtud->probeslen; } diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.h index 6b2e691..59876d5 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pmtud.h @@ -58,6 +58,10 @@ typedef struct ngtcp2_pmtud { /* min_fail_udp_payload_size is the minimum UDP payload size that is known to fail. */ size_t min_fail_udp_payload_size; + /* probes is the array of UDP datagram payload size to probe. */ + const uint16_t *probes; + /* probeslen is the number of probes pointed by probes. */ + size_t probeslen; } ngtcp2_pmtud; /* @@ -70,6 +74,10 @@ typedef struct ngtcp2_pmtud { * larger than or equal to all UDP payload probe candidates. * Therefore, call ngtcp2_pmtud_finished to check this situation. * + * The array pointed by |pmtud_probes| of length |pmtud_probeslen| + * specifies UDP datagram payload size to probe. If |pmtud_probeslen| + * is zero, the default probes are used. + * * This function returns 0 if it succeeds, or one of the following * negative error codes: * @@ -78,6 +86,7 @@ typedef struct ngtcp2_pmtud { */ int ngtcp2_pmtud_new(ngtcp2_pmtud **ppmtud, size_t max_udp_payload_size, size_t hard_max_udp_payload_size, int64_t tx_pkt_num, + const uint16_t *pmtud_probes, size_t pmtud_probeslen, const ngtcp2_mem *mem); /* diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.c index f7c122b..34363d0 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.c @@ -29,11 +29,13 @@ #include "ngtcp2_str.h" #include "ngtcp2_conv.h" +#include "ngtcp2_macro.h" void ngtcp2_ppe_init(ngtcp2_ppe *ppe, uint8_t *out, size_t outlen, - ngtcp2_crypto_cc *cc) { + size_t dgram_offset, ngtcp2_crypto_cc *cc) { ngtcp2_buf_init(&ppe->buf, out, outlen); + ppe->dgram_offset = dgram_offset; ppe->hdlen = 0; ppe->len_offset = 0; ppe->pkt_num_offset = 0; @@ -180,20 +182,6 @@ size_t ngtcp2_ppe_pktlen(ngtcp2_ppe *ppe) { return ngtcp2_buf_len(&ppe->buf) + cc->aead.max_overhead; } -size_t ngtcp2_ppe_padding(ngtcp2_ppe *ppe) { - ngtcp2_crypto_cc *cc = ppe->cc; - ngtcp2_buf *buf = &ppe->buf; - size_t len; - - assert(ngtcp2_buf_left(buf) >= cc->aead.max_overhead); - - len = ngtcp2_buf_left(buf) - cc->aead.max_overhead; - memset(buf->last, 0, len); - buf->last += len; - - return len; -} - size_t ngtcp2_ppe_padding_hp_sample(ngtcp2_ppe *ppe) { ngtcp2_crypto_cc *cc = ppe->cc; ngtcp2_buf *buf = &ppe->buf; @@ -220,6 +208,8 @@ size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n) { size_t pktlen = ngtcp2_buf_len(buf) + cc->aead.max_overhead; size_t len; + n = ngtcp2_min_size(n, ngtcp2_buf_cap(buf)); + if (pktlen >= n) { return 0; } @@ -230,6 +220,29 @@ size_t ngtcp2_ppe_padding_size(ngtcp2_ppe *ppe, size_t n) { return len; } +size_t ngtcp2_ppe_dgram_padding(ngtcp2_ppe *ppe) { + return ngtcp2_ppe_dgram_padding_size(ppe, NGTCP2_MAX_UDP_PAYLOAD_SIZE); +} + +size_t ngtcp2_ppe_dgram_padding_size(ngtcp2_ppe *ppe, size_t n) { + ngtcp2_crypto_cc *cc = ppe->cc; + ngtcp2_buf *buf = &ppe->buf; + size_t dgramlen = + ppe->dgram_offset + ngtcp2_buf_len(buf) + cc->aead.max_overhead; + size_t len; + + n = ngtcp2_min_size(n, ppe->dgram_offset + ngtcp2_buf_cap(buf)); + + if (dgramlen >= n) { + return 0; + } + + len = n - dgramlen; + buf->last = ngtcp2_setmem(buf->last, 0, len); + + return len; +} + int ngtcp2_ppe_ensure_hp_sample(ngtcp2_ppe *ppe) { ngtcp2_buf *buf = &ppe->buf; return ngtcp2_buf_left(buf) >= (4 - ppe->pkt_numlen) + NGTCP2_HP_SAMPLELEN; diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.h index 2a069ef..2f9275c 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ppe.h @@ -41,6 +41,9 @@ typedef struct ngtcp2_ppe { ngtcp2_buf buf; ngtcp2_crypto_cc *cc; + /* dgram_offset is the offset in UDP datagram payload that this QUIC + packet is positioned at. */ + size_t dgram_offset; /* hdlen is the number of bytes for packet header written in buf. */ size_t hdlen; /* len_offset is the offset to Length field. */ @@ -61,7 +64,7 @@ typedef struct ngtcp2_ppe { * ngtcp2_ppe_init initializes |ppe| with the given buffer. */ void ngtcp2_ppe_init(ngtcp2_ppe *ppe, uint8_t *out, size_t outlen, - ngtcp2_crypto_cc *cc); + size_t dgram_offset, ngtcp2_crypto_cc *cc); /* * ngtcp2_ppe_encode_hd encodes |hd|. @@ -110,13 +113,26 @@ size_t ngtcp2_ppe_left(ngtcp2_ppe *ppe); */ size_t ngtcp2_ppe_pktlen(ngtcp2_ppe *ppe); -/** - * @function +/* + * ngtcp2_ppe_dgram_padding is equivalent to call + * ngtcp2_ppe_dgram_padding_size(ppe, NGTCP2_MAX_UDP_PAYLOAD_SIZE). + * This function should be called just before calling + * ngtcp2_ppe_final(). + * + * This function returns the number of bytes padded. + */ +size_t ngtcp2_ppe_dgram_padding(ngtcp2_ppe *ppe); + +/* + * ngtcp2_ppe_dgram_padding_size adds PADDING frame so that the size + * of a UDP datagram payload is at least |n| bytes long. If it is + * unable to add PADDING in that way, this function still adds PADDING + * frame as much as possible. This function should be called just + * before calling ngtcp2_ppe_final(). * - * `ngtcp2_ppe_padding` encodes PADDING frames to the end of the - * buffer. This function returns the number of bytes padded. + * This function returns the number of bytes added as padding. */ -size_t ngtcp2_ppe_padding(ngtcp2_ppe *ppe); +size_t ngtcp2_ppe_dgram_padding_size(ngtcp2_ppe *ppe, size_t n); /* * ngtcp2_ppe_padding_hp_sample adds PADDING frame if the current diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pq.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pq.c index 5e1003d..96cde8f 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pq.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_pq.c @@ -69,7 +69,7 @@ int ngtcp2_pq_push(ngtcp2_pq *pq, ngtcp2_pq_entry *item) { void *nq; size_t ncapacity; - ncapacity = ngtcp2_max(4, (pq->capacity * 2)); + ncapacity = ngtcp2_max_size(4, pq->capacity * 2); nq = ngtcp2_mem_realloc(pq->mem, pq->q, ncapacity * sizeof(ngtcp2_pq_entry *)); diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h index b28a882..205ac62 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_ringbuf.h @@ -115,9 +115,8 @@ void *ngtcp2_ringbuf_get(ngtcp2_ringbuf *rb, size_t offset); int ngtcp2_ringbuf_full(ngtcp2_ringbuf *rb); /* ngtcp2_static_ringbuf_def defines ngtcp2_ringbuf struct wrapper - which uses a statically allocated buffer that is suitable for a - usage that does not change buffer size with ngtcp2_ringbuf_resize. - ngtcp2_ringbuf_free should never be called for rb field. */ + which uses a statically allocated buffer. ngtcp2_ringbuf_free + should never be called for rb field. */ #define ngtcp2_static_ringbuf_def(NAME, NMEMB, SIZE) \ typedef struct ngtcp2_static_ringbuf_##NAME { \ ngtcp2_ringbuf rb; \ diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c index 5cac383..4fa3b83 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rob.c @@ -149,7 +149,8 @@ static int rob_write_data(ngtcp2_rob *rob, uint64_t offset, const uint8_t *data, } } - n = (size_t)ngtcp2_min((uint64_t)len, d->range.begin + rob->chunk - offset); + n = (size_t)ngtcp2_min_uint64((uint64_t)len, + d->range.begin + rob->chunk - offset); memcpy(d->begin + (offset - d->range.begin), data, n); offset += n; data += n; @@ -278,8 +279,9 @@ size_t ngtcp2_rob_data_at(ngtcp2_rob *rob, const uint8_t **pdest, *pdest = d->begin + (offset - d->range.begin); - return (size_t)(ngtcp2_min(g->range.begin, d->range.begin + rob->chunk) - - offset); + return ( + size_t)(ngtcp2_min_uint64(g->range.begin, d->range.begin + rob->chunk) - + offset); } void ngtcp2_rob_pop(ngtcp2_rob *rob, uint64_t offset, size_t len) { diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c index 5ebdce7..89a0cb5 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_rtb.c @@ -53,7 +53,6 @@ static void rtb_entry_init(ngtcp2_rtb_entry *ent, const ngtcp2_pkt_hd *hd, ent->lost_ts = UINT64_MAX; ent->pktlen = pktlen; ent->flags = flags; - ent->next = NULL; } int ngtcp2_rtb_entry_objalloc_new(ngtcp2_rtb_entry **pent, @@ -581,7 +580,8 @@ static int rtb_process_acked_pkt(ngtcp2_rtb *rtb, ngtcp2_rtb_entry *ent, ngtcp2_pmtud_probe_success(conn->pmtud, ent->pktlen); conn->dcid.current.max_udp_payload_size = - ngtcp2_max(conn->dcid.current.max_udp_payload_size, ent->pktlen); + conn->cstat.max_tx_udp_payload_size = + ngtcp2_max(conn->dcid.current.max_udp_payload_size, ent->pktlen); if (ngtcp2_pmtud_finished(conn->pmtud)) { ngtcp2_conn_stop_pmtud(conn); @@ -971,7 +971,7 @@ static int rtb_pkt_lost(ngtcp2_rtb *rtb, ngtcp2_conn_stat *cstat, if (loss_time == UINT64_MAX) { loss_time = ent->ts + loss_delay; } else { - loss_time = ngtcp2_min(loss_time, ent->ts + loss_delay); + loss_time = ngtcp2_min_uint64(loss_time, ent->ts + loss_delay); } cstat->loss_time[rtb->pktns_id] = loss_time; @@ -1049,7 +1049,8 @@ static int rtb_detect_lost_pkt(ngtcp2_rtb *rtb, uint64_t *ppkt_lost, congestion_period = (cstat->smoothed_rtt + - ngtcp2_max(4 * cstat->rttvar, NGTCP2_GRANULARITY) + max_ack_delay) * + ngtcp2_max_uint64(4 * cstat->rttvar, NGTCP2_GRANULARITY) + + max_ack_delay) * NGTCP2_PERSISTENT_CONGESTION_THRESHOLD; start_ts = ngtcp2_max(rtb->persistent_congestion_start_ts, diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c new file mode 100644 index 0000000..77a68bd --- /dev/null +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.c @@ -0,0 +1,91 @@ +/* + * ngtcp2 + * + * Copyright (c) 2024 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ngtcp2_settings.h" + +#include <string.h> +#include <assert.h> + +#include "ngtcp2_unreachable.h" + +void ngtcp2_settings_default_versioned(int settings_version, + ngtcp2_settings *settings) { + size_t len = ngtcp2_settingslen_version(settings_version); + + memset(settings, 0, len); + + switch (settings_version) { + case NGTCP2_SETTINGS_VERSION: + case NGTCP2_SETTINGS_V1: + settings->cc_algo = NGTCP2_CC_ALGO_CUBIC; + settings->initial_rtt = NGTCP2_DEFAULT_INITIAL_RTT; + settings->ack_thresh = 2; + settings->max_tx_udp_payload_size = 1500 - 48; + settings->handshake_timeout = UINT64_MAX; + + break; + } +} + +static void settings_copy(ngtcp2_settings *dest, const ngtcp2_settings *src, + int settings_version) { + assert(settings_version != NGTCP2_SETTINGS_VERSION); + + memcpy(dest, src, ngtcp2_settingslen_version(settings_version)); +} + +const ngtcp2_settings * +ngtcp2_settings_convert_to_latest(ngtcp2_settings *dest, int settings_version, + const ngtcp2_settings *src) { + if (settings_version == NGTCP2_SETTINGS_VERSION) { + return src; + } + + ngtcp2_settings_default(dest); + + settings_copy(dest, src, settings_version); + + return dest; +} + +void ngtcp2_settings_convert_to_old(int settings_version, ngtcp2_settings *dest, + const ngtcp2_settings *src) { + assert(settings_version != NGTCP2_SETTINGS_VERSION); + + settings_copy(dest, src, settings_version); +} + +size_t ngtcp2_settingslen_version(int settings_version) { + ngtcp2_settings settings; + + switch (settings_version) { + case NGTCP2_SETTINGS_VERSION: + return sizeof(settings); + case NGTCP2_SETTINGS_V1: + return offsetof(ngtcp2_settings, initial_pkt_num) + + sizeof(settings.initial_pkt_num); + default: + ngtcp2_unreachable(); + } +} diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h new file mode 100644 index 0000000..8a8ddc2 --- /dev/null +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_settings.h @@ -0,0 +1,73 @@ +/* + * ngtcp2 + * + * Copyright (c) 2024 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef NGTCP2_SETTINGS_H +#define NGTCP2_SETTINGS_H + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <ngtcp2/ngtcp2.h> + +/* + * ngtcp2_settings_convert_to_latest converts |src| of version + * |settings_version| to the latest version NGTCP2_SETTINGS_VERSION. + * + * |dest| must point to the latest version. |src| may be the older + * version, and if so, it may have fewer fields. Accessing those + * fields causes undefined behavior. + * + * If |settings_version| == NGTCP2_SETTINGS_VERSION, no conversion is + * made, and |src| is returned. Otherwise, first |dest| is + * initialized via ngtcp2_settings_default, and then all valid fields + * in |src| are copied into |dest|. Finally, |dest| is returned. + */ +const ngtcp2_settings * +ngtcp2_settings_convert_to_latest(ngtcp2_settings *dest, int settings_version, + const ngtcp2_settings *src); + +/* + * ngtcp2_settings_convert_to_old converts |src| of the latest version + * to |dest| of version |settings_version|. + * + * |settings_version| must not be the latest version + * NGTCP2_SETTINGS_VERSION. + * + * |dest| points to the older version, and it may have fewer fields. + * Accessing those fields causes undefined behavior. + * + * This function copies all valid fields in version |settings_version| + * from |src| to |dest|. + */ +void ngtcp2_settings_convert_to_old(int settings_version, ngtcp2_settings *dest, + const ngtcp2_settings *src); + +/* + * ngtcp2_settingslen_version returns the effective length of + * ngtcp2_settings at the version |settings_version|. + */ +size_t ngtcp2_settingslen_version(int settings_version); + +#endif /* NGTCP2_SETTINGS_H */ diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h index 385302a..e396b24 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_strm.h @@ -86,6 +86,9 @@ typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; received from the remote endpoint. In this case, NGTCP2_STRM_FLAG_SHUT_WR is also set. */ #define NGTCP2_STRM_FLAG_STOP_SENDING_RECVED 0x800u +/* NGTCP2_STRM_FLAG_ANY_SENT indicates that any STREAM frame, + including empty one, has been sent. */ +#define NGTCP2_STRM_FLAG_ANY_SENT 0x1000u typedef struct ngtcp2_strm ngtcp2_strm; diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c new file mode 100644 index 0000000..5a2b346 --- /dev/null +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.c @@ -0,0 +1,886 @@ +/* + * ngtcp2 + * + * Copyright (c) 2023 ngtcp2 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "ngtcp2_transport_params.h" + +#include <string.h> +#include <assert.h> + +#include "ngtcp2_conv.h" +#include "ngtcp2_str.h" +#include "ngtcp2_mem.h" +#include "ngtcp2_unreachable.h" + +void ngtcp2_transport_params_default_versioned( + int transport_params_version, ngtcp2_transport_params *params) { + size_t len; + + switch (transport_params_version) { + case NGTCP2_TRANSPORT_PARAMS_VERSION: + len = sizeof(*params); + + break; + default: + ngtcp2_unreachable(); + } + + memset(params, 0, len); + + switch (transport_params_version) { + case NGTCP2_TRANSPORT_PARAMS_VERSION: + params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; + params->active_connection_id_limit = + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; + params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; + params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; + + break; + } +} + +/* + * varint_paramlen returns the length of a single transport parameter + * which has variable integer in its parameter. + */ +static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) { + size_t valuelen = ngtcp2_put_uvarintlen(param); + return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(valuelen) + valuelen; +} + +/* + * write_varint_param writes parameter |id| of the given |value| in + * varint encoding. It returns p + the number of bytes written. + */ +static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id, + uint64_t value) { + p = ngtcp2_put_uvarint(p, id); + p = ngtcp2_put_uvarint(p, ngtcp2_put_uvarintlen(value)); + return ngtcp2_put_uvarint(p, value); +} + +/* + * zero_paramlen returns the length of a single transport parameter + * which has zero length value in its parameter. + */ +static size_t zero_paramlen(ngtcp2_transport_param_id id) { + return ngtcp2_put_uvarintlen(id) + 1; +} + +/* + * write_zero_param writes parameter |id| that has zero length value. + * It returns p + the number of bytes written. + */ +static uint8_t *write_zero_param(uint8_t *p, ngtcp2_transport_param_id id) { + p = ngtcp2_put_uvarint(p, id); + *p++ = 0; + + return p; +} + +/* + * cid_paramlen returns the length of a single transport parameter + * which has |cid| as value. + */ +static size_t cid_paramlen(ngtcp2_transport_param_id id, + const ngtcp2_cid *cid) { + return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(cid->datalen) + + cid->datalen; +} + +/* + * write_cid_param writes parameter |id| of the given |cid|. It + * returns p + the number of bytes written. + */ +static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id, + const ngtcp2_cid *cid) { + assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN); + assert(cid->datalen <= NGTCP2_MAX_CIDLEN); + + p = ngtcp2_put_uvarint(p, id); + p = ngtcp2_put_uvarint(p, cid->datalen); + if (cid->datalen) { + p = ngtcp2_cpymem(p, cid->data, cid->datalen); + } + return p; +} + +static const uint8_t empty_address[16]; + +ngtcp2_ssize ngtcp2_transport_params_encode_versioned( + uint8_t *dest, size_t destlen, int transport_params_version, + const ngtcp2_transport_params *params) { + uint8_t *p; + size_t len = 0; + /* For some reason, gcc 7.3.0 requires this initialization. */ + size_t preferred_addrlen = 0; + size_t version_infolen = 0; + const ngtcp2_sockaddr_in *sa_in; + const ngtcp2_sockaddr_in6 *sa_in6; + ngtcp2_transport_params paramsbuf; + + params = ngtcp2_transport_params_convert_to_latest( + ¶msbuf, transport_params_version, params); + + if (params->original_dcid_present) { + len += + cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, + ¶ms->original_dcid); + } + + if (params->stateless_reset_token_present) { + len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) + + ngtcp2_put_uvarintlen(NGTCP2_STATELESS_RESET_TOKENLEN) + + NGTCP2_STATELESS_RESET_TOKENLEN; + } + + if (params->preferred_addr_present) { + assert(params->preferred_addr.cid.datalen >= NGTCP2_MIN_CIDLEN); + assert(params->preferred_addr.cid.datalen <= NGTCP2_MAX_CIDLEN); + preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ + + 16 /* ipv6Address */ + 2 /* ipv6Port */ + + 1 + params->preferred_addr.cid.datalen /* CID */ + + NGTCP2_STATELESS_RESET_TOKENLEN; + len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) + + ngtcp2_put_uvarintlen(preferred_addrlen) + preferred_addrlen; + } + if (params->retry_scid_present) { + len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, + ¶ms->retry_scid); + } + + if (params->initial_scid_present) { + len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, + ¶ms->initial_scid); + } + + if (params->initial_max_stream_data_bidi_local) { + len += varint_paramlen( + NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, + params->initial_max_stream_data_bidi_local); + } + if (params->initial_max_stream_data_bidi_remote) { + len += varint_paramlen( + NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, + params->initial_max_stream_data_bidi_remote); + } + if (params->initial_max_stream_data_uni) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI, + params->initial_max_stream_data_uni); + } + if (params->initial_max_data) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA, + params->initial_max_data); + } + if (params->initial_max_streams_bidi) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI, + params->initial_max_streams_bidi); + } + if (params->initial_max_streams_uni) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI, + params->initial_max_streams_uni); + } + if (params->max_udp_payload_size != + NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, + params->max_udp_payload_size); + } + if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT, + params->ack_delay_exponent); + } + if (params->disable_active_migration) { + len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); + } + if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, + params->max_ack_delay / NGTCP2_MILLISECONDS); + } + if (params->max_idle_timeout) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT, + params->max_idle_timeout / NGTCP2_MILLISECONDS); + } + if (params->active_connection_id_limit && + params->active_connection_id_limit != + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT, + params->active_connection_id_limit); + } + if (params->max_datagram_frame_size) { + len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE, + params->max_datagram_frame_size); + } + if (params->grease_quic_bit) { + len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); + } + if (params->version_info_present) { + version_infolen = + sizeof(uint32_t) + params->version_info.available_versionslen; + len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION) + + ngtcp2_put_uvarintlen(version_infolen) + version_infolen; + } + + if (dest == NULL && destlen == 0) { + return (ngtcp2_ssize)len; + } + + if (destlen < len) { + return NGTCP2_ERR_NOBUF; + } + + p = dest; + + if (params->original_dcid_present) { + p = write_cid_param( + p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID, + ¶ms->original_dcid); + } + + if (params->stateless_reset_token_present) { + p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN); + p = ngtcp2_put_uvarint(p, sizeof(params->stateless_reset_token)); + p = ngtcp2_cpymem(p, params->stateless_reset_token, + sizeof(params->stateless_reset_token)); + } + + if (params->preferred_addr_present) { + p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS); + p = ngtcp2_put_uvarint(p, preferred_addrlen); + + if (params->preferred_addr.ipv4_present) { + sa_in = ¶ms->preferred_addr.ipv4; + p = ngtcp2_cpymem(p, &sa_in->sin_addr, sizeof(sa_in->sin_addr)); + p = ngtcp2_put_uint16(p, sa_in->sin_port); + } else { + p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in->sin_addr)); + p = ngtcp2_put_uint16(p, 0); + } + + if (params->preferred_addr.ipv6_present) { + sa_in6 = ¶ms->preferred_addr.ipv6; + p = ngtcp2_cpymem(p, &sa_in6->sin6_addr, sizeof(sa_in6->sin6_addr)); + p = ngtcp2_put_uint16(p, sa_in6->sin6_port); + } else { + p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in6->sin6_addr)); + p = ngtcp2_put_uint16(p, 0); + } + + *p++ = (uint8_t)params->preferred_addr.cid.datalen; + if (params->preferred_addr.cid.datalen) { + p = ngtcp2_cpymem(p, params->preferred_addr.cid.data, + params->preferred_addr.cid.datalen); + } + p = ngtcp2_cpymem(p, params->preferred_addr.stateless_reset_token, + sizeof(params->preferred_addr.stateless_reset_token)); + } + + if (params->retry_scid_present) { + p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID, + ¶ms->retry_scid); + } + + if (params->initial_scid_present) { + p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID, + ¶ms->initial_scid); + } + + if (params->initial_max_stream_data_bidi_local) { + p = write_varint_param( + p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, + params->initial_max_stream_data_bidi_local); + } + + if (params->initial_max_stream_data_bidi_remote) { + p = write_varint_param( + p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, + params->initial_max_stream_data_bidi_remote); + } + + if (params->initial_max_stream_data_uni) { + p = write_varint_param(p, + NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI, + params->initial_max_stream_data_uni); + } + + if (params->initial_max_data) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA, + params->initial_max_data); + } + + if (params->initial_max_streams_bidi) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI, + params->initial_max_streams_bidi); + } + + if (params->initial_max_streams_uni) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI, + params->initial_max_streams_uni); + } + + if (params->max_udp_payload_size != + NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE, + params->max_udp_payload_size); + } + + if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT, + params->ack_delay_exponent); + } + + if (params->disable_active_migration) { + p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); + } + + if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, + params->max_ack_delay / NGTCP2_MILLISECONDS); + } + + if (params->max_idle_timeout) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT, + params->max_idle_timeout / NGTCP2_MILLISECONDS); + } + + if (params->active_connection_id_limit && + params->active_connection_id_limit != + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT, + params->active_connection_id_limit); + } + + if (params->max_datagram_frame_size) { + p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE, + params->max_datagram_frame_size); + } + + if (params->grease_quic_bit) { + p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); + } + + if (params->version_info_present) { + p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION); + p = ngtcp2_put_uvarint(p, version_infolen); + p = ngtcp2_put_uint32be(p, params->version_info.chosen_version); + if (params->version_info.available_versionslen) { + p = ngtcp2_cpymem(p, params->version_info.available_versions, + params->version_info.available_versionslen); + } + } + + assert((size_t)(p - dest) == len); + + return (ngtcp2_ssize)len; +} + +/* + * decode_varint decodes a single varint from the buffer pointed by + * |*pp| of length |end - *pp|. If it decodes an integer + * successfully, it stores the integer in |*pdest|, increment |*pp| by + * the number of bytes read from |*pp|, and returns 0. Otherwise it + * returns -1. + */ +static int decode_varint(uint64_t *pdest, const uint8_t **pp, + const uint8_t *end) { + const uint8_t *p = *pp; + size_t len; + + if (p == end) { + return -1; + } + + len = ngtcp2_get_uvarintlen(p); + if ((uint64_t)(end - p) < len) { + return -1; + } + + *pp = ngtcp2_get_uvarint(pdest, p); + + return 0; +} + +/* + * decode_varint_param decodes length prefixed value from the buffer + * pointed by |*pp| of length |end - *pp|. The length and value are + * encoded in varint form. If it decodes a value successfully, it + * stores the value in |*pdest|, increment |*pp| by the number of + * bytes read from |*pp|, and returns 0. Otherwise it returns -1. + */ +static int decode_varint_param(uint64_t *pdest, const uint8_t **pp, + const uint8_t *end) { + const uint8_t *p = *pp; + uint64_t valuelen; + + if (decode_varint(&valuelen, &p, end) != 0) { + return -1; + } + + if (p == end) { + return -1; + } + + if ((uint64_t)(end - p) < valuelen) { + return -1; + } + + if (ngtcp2_get_uvarintlen(p) != valuelen) { + return -1; + } + + *pp = ngtcp2_get_uvarint(pdest, p); + + return 0; +} + +/* + * decode_zero_param decodes zero length value from the buffer pointed + * by |*pp| of length |end - *pp|. The length is encoded in varint + * form. If it decodes zero length value successfully, it increments + * |*pp| by 1, and returns 0. Otherwise it returns -1. + */ +static int decode_zero_param(const uint8_t **pp, const uint8_t *end) { + if (*pp == end || **pp != 0) { + return -1; + } + + ++*pp; + + return 0; +} + +/* + * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer + * pointed by |*pp| of length |end - *pp|. The length is encoded in + * varint form. If it decodes a value successfully, it stores the + * value in |*pdest|, increment |*pp| by the number of read from + * |*pp|, and returns the number of bytes read. Otherwise it returns + * the one of the negative error code: + * + * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM + * Could not decode Connection ID. + */ +static int decode_cid_param(ngtcp2_cid *pdest, const uint8_t **pp, + const uint8_t *end) { + const uint8_t *p = *pp; + uint64_t valuelen; + + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) || + valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + ngtcp2_cid_init(pdest, p, (size_t)valuelen); + + p += valuelen; + + *pp = p; + + return 0; +} + +int ngtcp2_transport_params_decode_versioned(int transport_params_version, + ngtcp2_transport_params *dest, + const uint8_t *data, + size_t datalen) { + const uint8_t *p, *end, *lend; + size_t len; + uint64_t param_type; + uint64_t valuelen; + int rv; + ngtcp2_sockaddr_in *sa_in; + ngtcp2_sockaddr_in6 *sa_in6; + uint32_t version; + ngtcp2_transport_params *params, paramsbuf; + + if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { + params = dest; + } else { + params = ¶msbuf; + } + + /* Set default values */ + memset(params, 0, sizeof(*params)); + params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE; + params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT; + params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY; + params->active_connection_id_limit = + NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT; + + p = data; + end = data + datalen; + + for (; (size_t)(end - p) >= 2;) { + if (decode_varint(¶m_type, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + switch (param_type) { + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL: + if (decode_varint_param(¶ms->initial_max_stream_data_bidi_local, &p, + end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE: + if (decode_varint_param(¶ms->initial_max_stream_data_bidi_remote, &p, + end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI: + if (decode_varint_param(¶ms->initial_max_stream_data_uni, &p, end) != + 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA: + if (decode_varint_param(¶ms->initial_max_data, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI: + if (decode_varint_param(¶ms->initial_max_streams_bidi, &p, end) != + 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI: + if (decode_varint_param(¶ms->initial_max_streams_uni, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT: + if (decode_varint_param(¶ms->max_idle_timeout, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + params->max_idle_timeout *= NGTCP2_MILLISECONDS; + break; + case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE: + if (decode_varint_param(¶ms->max_udp_payload_size, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN: + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)valuelen != sizeof(params->stateless_reset_token)) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + p = ngtcp2_get_bytes(params->stateless_reset_token, p, + sizeof(params->stateless_reset_token)); + params->stateless_reset_token_present = 1; + + break; + case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT: + if (decode_varint_param(¶ms->ack_delay_exponent, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->ack_delay_exponent > 20) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS: + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)(end - p) < valuelen) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ + + 2 /* ipv6Port */ + + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN; + if (valuelen < len) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + sa_in = ¶ms->preferred_addr.ipv4; + + p = ngtcp2_get_bytes(&sa_in->sin_addr, p, sizeof(sa_in->sin_addr)); + p = ngtcp2_get_uint16be(&sa_in->sin_port, p); + + if (sa_in->sin_port || memcmp(empty_address, &sa_in->sin_addr, + sizeof(sa_in->sin_addr)) != 0) { + sa_in->sin_family = NGTCP2_AF_INET; + params->preferred_addr.ipv4_present = 1; + } + + sa_in6 = ¶ms->preferred_addr.ipv6; + + p = ngtcp2_get_bytes(&sa_in6->sin6_addr, p, sizeof(sa_in6->sin6_addr)); + p = ngtcp2_get_uint16be(&sa_in6->sin6_port, p); + + if (sa_in6->sin6_port || memcmp(empty_address, &sa_in6->sin6_addr, + sizeof(sa_in6->sin6_addr)) != 0) { + sa_in6->sin6_family = NGTCP2_AF_INET6; + params->preferred_addr.ipv6_present = 1; + } + + /* cid */ + params->preferred_addr.cid.datalen = *p++; + len += params->preferred_addr.cid.datalen; + if (valuelen != len || + params->preferred_addr.cid.datalen > NGTCP2_MAX_CIDLEN || + params->preferred_addr.cid.datalen < NGTCP2_MIN_CIDLEN) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->preferred_addr.cid.datalen) { + p = ngtcp2_get_bytes(params->preferred_addr.cid.data, p, + params->preferred_addr.cid.datalen); + } + + /* stateless reset token */ + p = ngtcp2_get_bytes( + params->preferred_addr.stateless_reset_token, p, + sizeof(params->preferred_addr.stateless_reset_token)); + params->preferred_addr_present = 1; + break; + case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION: + if (decode_zero_param(&p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + params->disable_active_migration = 1; + break; + case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID: + rv = decode_cid_param(¶ms->original_dcid, &p, end); + if (rv != 0) { + return rv; + } + params->original_dcid_present = 1; + break; + case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID: + rv = decode_cid_param(¶ms->retry_scid, &p, end); + if (rv != 0) { + return rv; + } + params->retry_scid_present = 1; + break; + case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID: + rv = decode_cid_param(¶ms->initial_scid, &p, end); + if (rv != 0) { + return rv; + } + params->initial_scid_present = 1; + break; + case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY: + if (decode_varint_param(¶ms->max_ack_delay, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (params->max_ack_delay >= 16384) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + params->max_ack_delay *= NGTCP2_MILLISECONDS; + break; + case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT: + if (decode_varint_param(¶ms->active_connection_id_limit, &p, end) != + 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE: + if (decode_varint_param(¶ms->max_datagram_frame_size, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + break; + case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT: + if (decode_zero_param(&p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + params->grease_quic_bit = 1; + break; + case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION: + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)(end - p) < valuelen) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (valuelen < sizeof(uint32_t) || (valuelen & 0x3)) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + p = ngtcp2_get_uint32(¶ms->version_info.chosen_version, p); + if (params->version_info.chosen_version == 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if (valuelen > sizeof(uint32_t)) { + params->version_info.available_versions = (uint8_t *)p; + params->version_info.available_versionslen = + (size_t)valuelen - sizeof(uint32_t); + + for (lend = p + (valuelen - sizeof(uint32_t)); p != lend;) { + p = ngtcp2_get_uint32(&version, p); + if (version == 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + } + } + params->version_info_present = 1; + break; + default: + /* Ignore unknown parameter */ + if (decode_varint(&valuelen, &p, end) != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + if ((size_t)(end - p) < valuelen) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + p += valuelen; + break; + } + } + + if (end - p != 0) { + return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; + } + + if (transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION) { + ngtcp2_transport_params_convert_to_old(transport_params_version, dest, + params); + } + + return 0; +} + +static int transport_params_copy_new(ngtcp2_transport_params **pdest, + const ngtcp2_transport_params *src, + const ngtcp2_mem *mem) { + size_t len = sizeof(**pdest); + ngtcp2_transport_params *dest; + uint8_t *p; + + if (src->version_info_present) { + len += src->version_info.available_versionslen; + } + + dest = ngtcp2_mem_malloc(mem, len); + if (dest == NULL) { + return NGTCP2_ERR_NOMEM; + } + + *dest = *src; + + if (src->version_info_present && src->version_info.available_versionslen) { + p = (uint8_t *)dest + sizeof(*dest); + memcpy(p, src->version_info.available_versions, + src->version_info.available_versionslen); + dest->version_info.available_versions = p; + } + + *pdest = dest; + + return 0; +} + +int ngtcp2_transport_params_decode_new(ngtcp2_transport_params **pparams, + const uint8_t *data, size_t datalen, + const ngtcp2_mem *mem) { + int rv; + ngtcp2_transport_params params; + + rv = ngtcp2_transport_params_decode(¶ms, data, datalen); + if (rv < 0) { + return rv; + } + + if (mem == NULL) { + mem = ngtcp2_mem_default(); + } + + return transport_params_copy_new(pparams, ¶ms, mem); +} + +void ngtcp2_transport_params_del(ngtcp2_transport_params *params, + const ngtcp2_mem *mem) { + if (params == NULL) { + return; + } + + if (mem == NULL) { + mem = ngtcp2_mem_default(); + } + + ngtcp2_mem_free(mem, params); +} + +int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest, + const ngtcp2_transport_params *src, + const ngtcp2_mem *mem) { + if (src == NULL) { + *pdest = NULL; + return 0; + } + + return transport_params_copy_new(pdest, src, mem); +} + +static void transport_params_copy(ngtcp2_transport_params *dest, + const ngtcp2_transport_params *src, + int transport_params_version) { + assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); + + switch (transport_params_version) { + case NGTCP2_TRANSPORT_PARAMS_V1: + memcpy(dest, src, + offsetof(ngtcp2_transport_params, version_info_present) + + sizeof(src->version_info_present)); + + break; + } +} + +const ngtcp2_transport_params * +ngtcp2_transport_params_convert_to_latest(ngtcp2_transport_params *dest, + int transport_params_version, + const ngtcp2_transport_params *src) { + if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) { + return src; + } + + ngtcp2_transport_params_default(dest); + + transport_params_copy(dest, src, transport_params_version); + + return dest; +} + +void ngtcp2_transport_params_convert_to_old( + int transport_params_version, ngtcp2_transport_params *dest, + const ngtcp2_transport_params *src) { + assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION); + + transport_params_copy(dest, src, transport_params_version); +} diff --git a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.h b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.h index 3457a8f..9b0acb8 100644 --- a/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_conversion.h +++ b/src/contrib/libngtcp2/ngtcp2/lib/ngtcp2_transport_params.h @@ -22,8 +22,8 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#ifndef NGTCP2_CONVERSION_H -#define NGTCP2_CONVERSION_H +#ifndef NGTCP2_TRANSPORT_PARAMS_H +#define NGTCP2_TRANSPORT_PARAMS_H #ifdef HAVE_CONFIG_H # include <config.h> @@ -31,6 +31,53 @@ #include <ngtcp2/ngtcp2.h> +/* ngtcp2_transport_param_id is the registry of QUIC transport + parameter ID. */ +typedef uint64_t ngtcp2_transport_param_id; + +#define NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID 0x00 +#define NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT 0x01 +#define NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN 0x02 +#define NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE 0x03 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA 0x04 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL 0x05 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE 0x06 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI 0x07 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI 0x08 +#define NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI 0x09 +#define NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT 0x0a +#define NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY 0x0b +#define NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION 0x0c +#define NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS 0x0d +#define NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT 0x0e +#define NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID 0x0f +#define NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID 0x10 +/* https://datatracker.ietf.org/doc/html/rfc9221 */ +#define NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE 0x20 +#define NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT 0x2ab2 +/* https://datatracker.ietf.org/doc/html/rfc9368 */ +#define NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION 0x11 + +/* NGTCP2_MAX_STREAMS is the maximum number of streams. */ +#define NGTCP2_MAX_STREAMS (1LL << 60) + +/* + * ngtcp2_transport_params_copy_new makes a copy of |src|, and assigns + * it to |*pdest|. If |src| is NULL, NULL is assigned to |*pdest|. + * + * Caller is responsible to call ngtcp2_transport_params_del to free + * the memory assigned to |*pdest|. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * NGTCP2_ERR_NOMEM + * Out of memory. + */ +int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest, + const ngtcp2_transport_params *src, + const ngtcp2_mem *mem); + /* * ngtcp2_transport_params_convert_to_latest converts |src| of version * |transport_params_version| to the latest version @@ -68,4 +115,4 @@ void ngtcp2_transport_params_convert_to_old(int transport_params_version, ngtcp2_transport_params *dest, const ngtcp2_transport_params *src); -#endif /* NGTCP2_CONVERSION_H */ +#endif /* NGTCP2_TRANSPORT_PARAMS_H */ diff --git a/src/contrib/libngtcp2/ngtcp2/ngtcp2.h b/src/contrib/libngtcp2/ngtcp2/ngtcp2.h index 72c8142..0b49853 100644 --- a/src/contrib/libngtcp2/ngtcp2/ngtcp2.h +++ b/src/contrib/libngtcp2/ngtcp2/ngtcp2.h @@ -1689,7 +1689,8 @@ typedef enum ngtcp2_token_type { } ngtcp2_token_type; #define NGTCP2_SETTINGS_V1 1 -#define NGTCP2_SETTINGS_VERSION NGTCP2_SETTINGS_V1 +#define NGTCP2_SETTINGS_V2 2 +#define NGTCP2_SETTINGS_VERSION NGTCP2_SETTINGS_V2 /** * @struct @@ -1723,8 +1724,7 @@ typedef struct ngtcp2_settings { ngtcp2_printf log_printf; /** * :member:`max_tx_udp_payload_size` is the maximum size of UDP - * datagram payload that the local endpoint transmits. It is used - * by congestion controller to compute congestion window. + * datagram payload that the local endpoint transmits. */ size_t max_tx_udp_payload_size; /** @@ -1877,6 +1877,24 @@ typedef struct ngtcp2_settings { * number space. It must be in range [0, INT32_MAX], inclusive. */ uint32_t initial_pkt_num; + /* The following fields have been added since NGTCP2_SETTINGS_V2. */ + /** + * :member:`pmtud_probes` is the array of UDP datagram payload size + * to probe during Path MTU Discovery. The discovery is done in the + * order appeared in this array. The size must be strictly larger + * than 1200, otherwise the behavior is undefined. The maximum + * value in this array should be set to + * :member:`max_tx_udp_payload_size`. If this field is not set, the + * predefined PMTUD probes are made. This field has been available + * since v1.4.0. + */ + const uint16_t *pmtud_probes; + /** + * :member:`pmtud_probeslen` is the number of elements that are + * contained in the array pointed by :member:`pmtud_probes`. This + * field has been available since v1.4.0. + */ + size_t pmtud_probeslen; } ngtcp2_settings; /** @@ -4388,7 +4406,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * handshake as well. * * |destlen| should be at least - * :member:`ngtcp2_settings.max_tx_udp_payload_size`. + * :member:`ngtcp2_settings.max_tx_udp_payload_size`. It must be at + * least :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`. * * Specifying -1 to |stream_id| means no new stream data to send. * @@ -4418,8 +4437,10 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_stream_versioned( * In that case, |*pdatalen| would be -1 if |pdatalen| is not * ``NULL``. * - * If |flags| & :macro:`NGTCP2_WRITE_STREAM_FLAG_FIN` is nonzero, and - * 0 length STREAM frame is successfully serialized, |*pdatalen| would + * Empty data is treated specially, and it is only accepted if no + * data, including the empty data, is submitted to a stream or + * :macro:`NGTCP2_WRITE_STREAM_FLAG_FIN` is set in |flags|. If 0 + * length STREAM frame is successfully serialized, |*pdatalen| would * be 0. * * The number of data encoded in STREAM frame is stored in |*pdatalen| @@ -4573,7 +4594,8 @@ NGTCP2_EXTERN ngtcp2_ssize ngtcp2_conn_write_datagram_versioned( * as well. * * |destlen| should be at least - * :member:`ngtcp2_settings.max_tx_udp_payload_size`. + * :member:`ngtcp2_settings.max_tx_udp_payload_size`. It must be at + * least :macro:`NGTCP2_MAX_UDP_PAYLOAD_SIZE`. * * For |path| and |pi| parameters, refer to * `ngtcp2_conn_writev_stream`. @@ -5193,7 +5215,19 @@ typedef enum ngtcp2_ccerr_type { * transport error, and it indicates that connection is closed * because of idle timeout. */ - NGTCP2_CCERR_TYPE_IDLE_CLOSE + NGTCP2_CCERR_TYPE_IDLE_CLOSE, + /** + * :enum:`NGTCP2_CCERR_TYPE_DROP_CONN` is a special case of QUIC + * transport error, and it indicates that connection should be + * dropped without sending a CONNECTION_CLOSE frame. + */ + NGTCP2_CCERR_TYPE_DROP_CONN, + /** + * :enum:`NGTCP2_CCERR_TYPE_RETRY` is a special case of QUIC + * transport error, and it indicates that RETRY packet should be + * sent to a client. + */ + NGTCP2_CCERR_TYPE_RETRY } ngtcp2_ccerr_type; /** @@ -5284,6 +5318,18 @@ NGTCP2_EXTERN void ngtcp2_ccerr_set_transport_error(ngtcp2_ccerr *ccerr, * :member:`ccerr->error_code <ngtcp2_ccerr.error_code>` to * :macro:`NGTCP2_NO_ERROR`. * + * If |liberr| is :macro:`NGTCP2_ERR_DROP_CONN`, :member:`ccerr->type + * <ngtcp2_ccerr.type>` is set to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_DROP_CONN`, and + * :member:`ccerr->error_code <ngtcp2_ccerr.error_code>` to + * :macro:`NGTCP2_NO_ERROR`. + * + * If |liberr| is :macro:`NGTCP2_ERR_RETRY`, :member:`ccerr->type + * <ngtcp2_ccerr.type>` is set to + * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_RETRY`, and + * :member:`ccerr->error_type <ngtcp2_ccerr.error_code>` to + * :macro:`NGTCP2_NO_ERROR`. + * * Otherwise, :member:`ccerr->type <ngtcp2_ccerr.type>` is set to * :enum:`ngtcp2_ccerr_type.NGTCP2_CCERR_TYPE_TRANSPORT`, and * :member:`ccerr->error_code <ngtcp2_ccerr.error_code>` is set to an diff --git a/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h b/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h index 06427d7..9f909bf 100644 --- a/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h +++ b/src/contrib/libngtcp2/ngtcp2/ngtcp2_crypto.h @@ -540,7 +540,7 @@ NGTCP2_EXTERN int ngtcp2_crypto_generate_stateless_reset_token( * `ngtcp2_crypto_generate_retry_token` or * `ngtcp2_crypto_generate_regular_token`. */ -#define NGTCP2_CRYPTO_TOKEN_RAND_DATALEN 32 +#define NGTCP2_CRYPTO_TOKEN_RAND_DATALEN 16 /** * @macro diff --git a/src/contrib/libngtcp2/ngtcp2/version.h b/src/contrib/libngtcp2/ngtcp2/version.h index 801c6cb..9eb076d 100644 --- a/src/contrib/libngtcp2/ngtcp2/version.h +++ b/src/contrib/libngtcp2/ngtcp2/version.h @@ -36,7 +36,7 @@ * * Version number of the ngtcp2 library release. */ -#define NGTCP2_VERSION "1.3.0" +#define NGTCP2_VERSION "1.5.0" /** * @macro @@ -46,6 +46,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGTCP2_VERSION_NUM 0x010300 +#define NGTCP2_VERSION_NUM 0x010500 #endif /* VERSION_H */ diff --git a/src/knot/conf/base.c b/src/knot/conf/base.c index 9dc4cef..51caf10 100644 --- a/src/knot/conf/base.c +++ b/src/knot/conf/base.c @@ -27,6 +27,7 @@ #include "libknot/yparser/ypformat.h" #include "libknot/yparser/yptrafo.h" #include "contrib/files.h" +#include "contrib/json.h" #include "contrib/sockaddr.h" #include "contrib/string.h" @@ -1073,3 +1074,230 @@ export_error: return ret; } + +/* + * Execute the provided block of code twice: first to handle a JSON schema for + * a single item, and then to define an array of these items. + */ +#define SINGLE_OR_ARRAY(code_block) \ +do { \ + if (item->flags & YP_FMULTI) { \ + jsonw_list(w, "oneOf"); \ + jsonw_object(w, NULL); \ + { code_block } \ + jsonw_end(w); \ + jsonw_object(w, NULL); \ + jsonw_str(w, "type", "array"); \ + jsonw_object(w, "items"); \ + } \ + { code_block } \ + if (item->flags & YP_FMULTI) { \ + jsonw_end(w); \ + jsonw_end(w); \ + jsonw_end(w); \ + } \ +} while (0) + +static int export_group_items(jsonw_t *w, const yp_item_t *item, bool array); + +static void export_type(jsonw_t *w, const yp_item_t *item) +{ + switch (item->type) { + case YP_TINT: + SINGLE_OR_ARRAY( + switch (item->var.i.unit) { + case YP_SSIZE: + jsonw_str(w, "$ref", "#/$defs/int_size"); + break; + case YP_STIME: + jsonw_str(w, "$ref", "#/$defs/int_time"); + break; + default: + jsonw_str(w, "$ref", "#/$defs/int"); + break; + } + ); + break; + case YP_TBOOL: + SINGLE_OR_ARRAY( + jsonw_str(w, "$ref", "#/$defs/switch"); + ); + break; + case YP_TOPT: + SINGLE_OR_ARRAY( + jsonw_str(w, "type", "string"); + jsonw_list(w, "enum"); + for (const knot_lookup_t *o = item->var.o.opts; + o->name != NULL; ++o) { + jsonw_str(w, NULL, o->name); + } + jsonw_end(w); + ); + break; + case YP_TSTR: + SINGLE_OR_ARRAY( + jsonw_str(w, "type", "string"); + ); + break; + case YP_TDNAME: + SINGLE_OR_ARRAY( + jsonw_str(w, "$ref", "#/$defs/dname"); + ); + break; + case YP_TB64: + SINGLE_OR_ARRAY( + jsonw_str(w, "$ref", "#/$defs/base64"); + ); + break; + case YP_TGRP: + export_group_items(w, item->sub_items, item->flags & YP_FMULTI); + break; + case YP_THEX: + case YP_TADDR: + case YP_TNET: + case YP_TDATA: + case YP_TREF: + SINGLE_OR_ARRAY( + jsonw_str(w, "type", "string"); + ); + break; + default: + assert(0); + break; + } +} + +static int export_group_items(jsonw_t *w, const yp_item_t *item, bool array) +{ + assert(w != NULL && item != NULL); + + if (array) { + jsonw_list(w, "type"); + jsonw_str(w, NULL, "array"); + jsonw_str(w, NULL, "null"); + jsonw_end(w); + jsonw_object(w, "items"); + } + + jsonw_list(w, "type"); + jsonw_str(w, NULL, "object"); + jsonw_str(w, NULL, "null"); + jsonw_end(w); + jsonw_bool(w, "additionalProperties", false); + jsonw_object(w, "properties"); + for (; item->name != NULL; ++item) { + jsonw_object(w, item->name + 1); + export_type(w, item); + jsonw_end(w); + } + jsonw_end(w); + + if (array) { + jsonw_end(w); + } + + return KNOT_EOK; +} + +int conf_export_schema( + conf_t *conf, + const char *file_name) +{ + if (conf == NULL) { + return KNOT_EINVAL; + } + + FILE *fp = (file_name != NULL) ? fopen(file_name, "w") : stdout; + if (fp == NULL) { + return knot_map_errno(); + } + + jsonw_t *w = jsonw_new(fp, " "); + jsonw_object(w, NULL); + + // JSON-Schema header + jsonw_str(w, "$schema", "https://json-schema.org/draft/2020-12/schema"); + jsonw_str(w, "$id", "https://knot-dns.cz/config.schema.json"); + jsonw_str(w, "title", "Knot DNS configuration schema"); + jsonw_str(w, "description", "Version Knot DNS " PACKAGE_VERSION); + + // Define own types + jsonw_object(w, "$defs"); + // Switch type + jsonw_object(w, "switch"); + jsonw_list(w, "oneOf"); + jsonw_object(w, NULL); + jsonw_str(w, "type", "boolean"); + jsonw_end(w); + jsonw_object(w, NULL); + jsonw_str(w, "type", "string"); + jsonw_list(w, "enum"); + jsonw_str(w, NULL, "on"); + jsonw_str(w, NULL, "off"); + jsonw_str(w, NULL, "true"); + jsonw_str(w, NULL, "false"); + jsonw_end(w); + jsonw_end(w); + jsonw_end(w); + jsonw_end(w); + // Base64 type + jsonw_object(w, "base64"); + jsonw_str(w, "type", "string"); + jsonw_str(w, "pattern", "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]===)?$"); + jsonw_end(w); + // DNAME type + jsonw_object(w, "dname"); + jsonw_str(w, "type", "string"); + jsonw_str(w, "pattern", "^(([a-zA-Z0-9_*/-]|(\\\\[^0-9])|(\\\\(([0-1][0-9][0-9])|(2[0-4][0-9])|(25[0-5]))))\\.?)+$"); + jsonw_end(w); + // Integer type + jsonw_object(w, "int"); + jsonw_list(w, "oneOf"); + jsonw_object(w, NULL); + jsonw_str(w, "type", "integer"); + jsonw_end(w); + jsonw_object(w, NULL); + jsonw_str(w, "type", "string"); + jsonw_str(w, "pattern", "^[+-]?[0-9]+$"); + jsonw_end(w); + jsonw_end(w); + jsonw_end(w); + // Size integer type + jsonw_object(w, "int_size"); + jsonw_list(w, "oneOf"); + jsonw_object(w, NULL); + jsonw_str(w, "type", "integer"); + jsonw_end(w); + jsonw_object(w, NULL); + jsonw_str(w, "type", "string"); + jsonw_str(w, "pattern", "^[+-]?[0-9]+[BKMG]?$"); + jsonw_end(w); + jsonw_end(w); + jsonw_end(w); + // Time integer type + jsonw_object(w, "int_time"); + jsonw_list(w, "oneOf"); + jsonw_object(w, NULL); + jsonw_str(w, "type", "integer"); + jsonw_end(w); + jsonw_object(w, NULL); + jsonw_str(w, "type", "string"); + jsonw_str(w, "pattern", "^[+-]?[0-9]+[smhd]?$"); + jsonw_end(w); + jsonw_end(w); + jsonw_end(w); + // END + jsonw_end(w); + + // Export configuration schema + int ret = export_group_items(w, conf->schema, false); + + jsonw_end(w); + jsonw_free(&w); + + if (file_name != NULL) { + fclose(fp); + } + + return ret; +} diff --git a/src/knot/conf/base.h b/src/knot/conf/base.h index 2fc48de..5c77cac 100644 --- a/src/knot/conf/base.h +++ b/src/knot/conf/base.h @@ -331,3 +331,16 @@ int conf_export( const char *file_name, yp_style_t style ); + +/*! + * Exports configuration schema in JSON. + * + * \param[in] conf Configuration. + * \param[in] file_name Output filename (stdout is used if NULL). + * + * \return Error code, KNOT_EOK if success. + */ +int conf_export_schema( + conf_t *conf, + const char *file_name +); diff --git a/src/knot/conf/conf.c b/src/knot/conf/conf.c index 54eeae6..55ee971 100644 --- a/src/knot/conf/conf.c +++ b/src/knot/conf/conf.c @@ -191,6 +191,10 @@ conf_val_t conf_zone_get_txn( conf_db_get(conf, txn, C_ZONE, key1_name, dname, dname_size, &val); switch (val.code) { case KNOT_EOK: + if (val.blob_len == 1 && (val.item->flags & CONF_REF_EMPTY)) { + static const conf_val_t empty = { .code = KNOT_ENOENT }; + return empty; + } return val; default: CONF_LOG_ZONE(LOG_ERR, dname, "failed to read '%s/%s' (%s)", diff --git a/src/knot/conf/conf.h b/src/knot/conf/conf.h index 99af9bd..562722d 100644 --- a/src/knot/conf/conf.h +++ b/src/knot/conf/conf.h @@ -21,6 +21,21 @@ #include "knot/conf/base.h" #include "knot/conf/schema.h" +/*! Configuration schema additional flags. */ +#define CONF_IO_FACTIVE YP_FUSR1 /*!< Active confio transaction indicator. */ +#define CONF_IO_FZONE YP_FUSR2 /*!< Zone section indicator. */ +#define CONF_IO_FREF YP_FUSR3 /*!< Possibly referenced id from a zone. */ +#define CONF_IO_FDIFF_ZONES YP_FUSR4 /*!< All zones config has changed. */ +#define CONF_IO_FCHECK_ZONES YP_FUSR5 /*!< All zones config needs to check. */ +#define CONF_IO_FRLD_SRV YP_FUSR6 /*!< Reload server. */ +#define CONF_IO_FRLD_LOG YP_FUSR7 /*!< Reload logging. */ +#define CONF_IO_FRLD_MOD YP_FUSR8 /*!< Reload global modules. */ +#define CONF_IO_FRLD_ZONE YP_FUSR9 /*!< Reload a specific zone. */ +#define CONF_IO_FRLD_ZONES YP_FUSR10 /*!< Reload all zones. */ +#define CONF_REF_EMPTY YP_FUSR11 /*!< Allow empty reference value for zone item. */ +#define CONF_IO_FRLD_ALL (CONF_IO_FRLD_SRV | CONF_IO_FRLD_LOG | \ + CONF_IO_FRLD_MOD | CONF_IO_FRLD_ZONES) + /*! Configuration remote getter output. */ typedef struct { /*! Target socket address. */ diff --git a/src/knot/conf/confio.h b/src/knot/conf/confio.h index be08e97..1f3a481 100644 --- a/src/knot/conf/confio.h +++ b/src/knot/conf/confio.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,20 +18,6 @@ #include "knot/conf/conf.h" -/*! Configuration schema additional flags for dynamic changes. */ -#define CONF_IO_FACTIVE YP_FUSR1 /*!< Active confio transaction indicator. */ -#define CONF_IO_FZONE YP_FUSR2 /*!< Zone section indicator. */ -#define CONF_IO_FREF YP_FUSR3 /*!< Possibly referenced id from a zone. */ -#define CONF_IO_FDIFF_ZONES YP_FUSR4 /*!< All zones config has changed. */ -#define CONF_IO_FCHECK_ZONES YP_FUSR5 /*!< All zones config needs to check. */ -#define CONF_IO_FRLD_SRV YP_FUSR6 /*!< Reload server. */ -#define CONF_IO_FRLD_LOG YP_FUSR7 /*!< Reload logging. */ -#define CONF_IO_FRLD_MOD YP_FUSR8 /*!< Reload global modules. */ -#define CONF_IO_FRLD_ZONE YP_FUSR9 /*!< Reload a specific zone. */ -#define CONF_IO_FRLD_ZONES YP_FUSR10 /*!< Reload all zones. */ -#define CONF_IO_FRLD_ALL (CONF_IO_FRLD_SRV | CONF_IO_FRLD_LOG | \ - CONF_IO_FRLD_MOD | CONF_IO_FRLD_ZONES) - /*! Zone configuration change type. */ typedef enum { CONF_IO_TNONE = 0, /*!< Unspecified. */ diff --git a/src/knot/conf/schema.c b/src/knot/conf/schema.c index 59c6796..6e426b3 100644 --- a/src/knot/conf/schema.c +++ b/src/knot/conf/schema.c @@ -282,6 +282,7 @@ static const yp_item_t desc_xdp[] = { static const yp_item_t desc_control[] = { { C_LISTEN, YP_TSTR, YP_VSTR = { "knot.sock" } }, + { C_BACKLOG, YP_TINT, YP_VINT = { 0, UINT16_MAX, 5 } }, { C_TIMEOUT, YP_TINT, YP_VINT = { 0, INT32_MAX / 1000, 5, YP_STIME } }, { C_COMMENT, YP_TSTR, YP_VNONE }, { NULL } @@ -418,6 +419,7 @@ static const yp_item_t desc_policy[] = { CONF_IO_FRLD_ZONES }, { C_ZONE_MAX_TTL, YP_TINT, YP_VINT = { 0, INT32_MAX, YP_NIL, YP_STIME }, CONF_IO_FRLD_ZONES }, + { C_KEYTAG_MODULO, YP_TSTR, YP_VSTR = { "0/1" }, YP_FNONE, { check_modulo } }, \ { C_KSK_LIFETIME, YP_TINT, YP_VINT = { 0, UINT32_MAX, 0, YP_STIME }, CONF_IO_FRLD_ZONES }, { C_ZSK_LIFETIME, YP_TINT, YP_VINT = { 0, UINT32_MAX, DAYS(30), YP_STIME }, @@ -460,9 +462,11 @@ static const yp_item_t desc_policy[] = { #define ZONE_ITEMS(FLAGS) \ { C_STORAGE, YP_TSTR, YP_VSTR = { STORAGE_DIR }, FLAGS }, \ { C_FILE, YP_TSTR, YP_VNONE, FLAGS }, \ - { C_MASTER, YP_TREF, YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI, { check_ref } }, \ + { C_MASTER, YP_TREF, YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI | CONF_REF_EMPTY, \ + { check_ref } }, \ { C_DDNS_MASTER, YP_TREF, YP_VREF = { C_RMT }, YP_FNONE, { check_ref_empty } }, \ - { C_NOTIFY, YP_TREF, YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI, { check_ref } }, \ + { C_NOTIFY, YP_TREF, YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI | CONF_REF_EMPTY, \ + { check_ref } }, \ { C_ACL, YP_TREF, YP_VREF = { C_ACL }, YP_FMULTI, { check_ref } }, \ { C_MASTER_PIN_TOL, YP_TINT, YP_VINT = { 0, UINT32_MAX, 0, YP_STIME } }, \ { C_PROVIDE_IXFR, YP_TBOOL, YP_VBOOL = { true } }, \ @@ -480,7 +484,7 @@ static const yp_item_t desc_policy[] = { { C_DNSSEC_SIGNING, YP_TBOOL, YP_VNONE, FLAGS }, \ { C_DNSSEC_VALIDATION, YP_TBOOL, YP_VNONE, FLAGS }, \ { C_DNSSEC_POLICY, YP_TREF, YP_VREF = { C_POLICY }, FLAGS, { check_ref_dflt } }, \ - { C_DS_PUSH, YP_TREF, YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI | FLAGS, \ + { C_DS_PUSH, YP_TREF, YP_VREF = { C_RMT, C_RMTS }, YP_FMULTI | CONF_REF_EMPTY | FLAGS, \ { check_ref } }, \ { C_REVERSE_GEN, YP_TDNAME,YP_VNONE, FLAGS | CONF_IO_FRLD_ZONES }, \ { C_SERIAL_POLICY, YP_TOPT, YP_VOPT = { serial_policies, SERIAL_POLICY_INCREMENT } }, \ diff --git a/src/knot/conf/schema.h b/src/knot/conf/schema.h index 1850380..96d29c1 100644 --- a/src/knot/conf/schema.h +++ b/src/knot/conf/schema.h @@ -30,6 +30,7 @@ #define C_ASYNC_START "\x0B""async-start" #define C_AUTO_ACL "\x0D""automatic-acl" #define C_BACKEND "\x07""backend" +#define C_BACKLOG "\x07""backlog" #define C_BG_WORKERS "\x12""background-workers" #define C_BLOCK_NOTIFY_XFR "\x1B""block-notify-after-transfer" #define C_CATALOG_DB "\x0A""catalog-db" @@ -83,6 +84,7 @@ #define C_DELETE_DELAY "\x0C""delete-delay" #define C_KEY "\x03""key" #define C_KEYSTORE "\x08""keystore" +#define C_KEYTAG_MODULO "\x0D""keytag-modulo" #define C_KEY_FILE "\x08""key-file" #define C_KEY_LABEL "\x09""key-label" #define C_KSK_LIFETIME "\x0C""ksk-lifetime" diff --git a/src/knot/conf/tools.c b/src/knot/conf/tools.c index 965c49c..e232fba 100644 --- a/src/knot/conf/tools.c +++ b/src/knot/conf/tools.c @@ -238,6 +238,13 @@ int check_ref( bool found1 = false, found2 = false; + // Check if allowed empty value for specific zone items. + if (args->data_len == 1 && (args->item->flags & CONF_REF_EMPTY) && + args->item->parent->name[0] == C_ZONE[0] && + memcmp(&args->item->parent->name[1], &C_ZONE[1], C_ZONE[0]) == 0) { + return KNOT_EOK; + } + // Try to find the id in the first section. found1 = conf_rawid_exists_txn(args->extra->conf, args->extra->txn, ref->name, args->data, args->data_len); @@ -963,15 +970,44 @@ int check_template( #define CHECK_CATZ_TPL(option, option_string) \ { \ - conf_val_t val = conf_rawid_get_txn(args->extra->conf, args->extra->txn, \ - C_TPL, option, catalog_tpl.data, \ - catalog_tpl.len); \ + val = conf_rawid_get_txn(args->extra->conf, args->extra->txn, \ + C_TPL, option, tpl->data, tpl->len); \ if (val.code == KNOT_EOK) { \ - args->err_str = "'" option_string "' in a catalog template"; \ + args->err_str = "'" option_string "' not compatible with the role"; \ return KNOT_EINVAL; \ } \ } +static int sub_check_catalog_tpl( + knotd_conf_check_args_t *args, + conf_val_t *tpl) +{ + conf_val_t val = conf_rawid_get_txn(args->extra->conf, args->extra->txn, + C_TPL, C_CATALOG_ROLE, tpl->data, tpl->len); + switch (conf_opt(&val)) { + case CATALOG_ROLE_MEMBER: + val = conf_rawid_get_txn(args->extra->conf, args->extra->txn, + C_TPL, C_CATALOG_ZONE, tpl->data, tpl->len); + if (val.code != KNOT_EOK) { + args->err_str = "no catalog zone defined"; + return KNOT_EINVAL; + } + CHECK_CATZ_TPL(C_CATALOG_TPL, "catalog-template"); + return KNOT_EOK; + case CATALOG_ROLE_INTERPRET: + args->err_str = "catalog role interpret in a catalog template"; + return KNOT_EINVAL; + case CATALOG_ROLE_GENERATE: + args->err_str = "catalog role generate in a catalog template"; + return KNOT_EINVAL; + default: + CHECK_CATZ_TPL(C_CATALOG_TPL, "catalog-template"); + CHECK_CATZ_TPL(C_CATALOG_ZONE, "catalog-zone"); + CHECK_CATZ_TPL(C_CATALOG_GROUP, "catalog-group"); + return KNOT_EOK; + } +} + int check_zone( knotd_conf_check_args_t *args) { @@ -1057,10 +1093,9 @@ int check_zone( if (role == CATALOG_ROLE_INTERPRET) { conf_val(&catalog_tpl); while (catalog_tpl.code == KNOT_EOK) { - CHECK_CATZ_TPL(C_CATALOG_TPL, "catalog-template"); - CHECK_CATZ_TPL(C_CATALOG_ROLE, "catalog-role"); - CHECK_CATZ_TPL(C_CATALOG_ZONE, "catalog-zone"); - CHECK_CATZ_TPL(C_CATALOG_GROUP, "catalog-group"); + if (sub_check_catalog_tpl(args, &catalog_tpl) != KNOT_EOK) { + return KNOT_EINVAL; + } conf_val_next(&catalog_tpl); } } diff --git a/src/knot/ctl/commands.c b/src/knot/ctl/commands.c index 693bc59..c34709d 100644 --- a/src/knot/ctl/commands.c +++ b/src/knot/ctl/commands.c @@ -70,6 +70,20 @@ static struct { sizeof(((send_ctx_t *)0)->rdata)]; } ctl_globals; +static bool allow_blocking_while_ctl_txn(zone_event_type_t event) +{ + // this can be allowed for those events that do NOT create a zone_update_t + switch (event) { + case ZONE_EVENT_UFREEZE: + case ZONE_EVENT_UTHAW: + case ZONE_EVENT_NOTIFY: + case ZONE_EVENT_FLUSH: + return true; + default: + return false; + } +} + /*! * Evaluates a filter pair and checks for conflicting filters. * @@ -110,6 +124,10 @@ static int schedule_trigger(zone_t *zone, ctl_args_t *args, zone_event_type_t ev int ret = KNOT_EOK; if (ctl_has_flag(args->data[KNOT_CTL_IDX_FLAGS], CTL_FLAG_BLOCKING)) { + if (!allow_blocking_while_ctl_txn(event) && + zone->control_update != NULL) { + return KNOT_TXN_EEXISTS; + } ret = zone_events_schedule_blocking(zone, event, user); } else if (user) { zone_events_schedule_user(zone, event); @@ -562,6 +580,10 @@ static int init_backup(ctl_args_t *args, bool restore_mode) // Evaluate filters (and possibly fail) before writing to the filesystem. knot_backup_params_t filters = 0; knot_backup_params_t dflts = restore_mode ? BACKUP_PARAM_DFLT_R : BACKUP_PARAM_DFLT_B; + + // Filter '+keysonly' silently changes all defaults to '+no...'. + dflts = MATCH_AND_FILTER(args, BACKUP_PARAM_KEYSONLY) ? BACKUP_PARAM_EMPTY : dflts; + for (const backup_filter_list_t *item = backup_filters; item->name != NULL; item++) { if (!eval_backup_filters(args, &filters, item, dflts)) { return KNOT_EXPARAM; @@ -629,6 +651,12 @@ static int zone_backup_cmd(zone_t *zone, ctl_args_t *args) return KNOT_EPROGRESS; } + if (ctx->restore_mode && zone->control_update != NULL) { + log_zone_warning(zone->name, "restoring backup not possible due to open control transaction"); + ctx->failed = true; + return KNOT_TXN_EEXISTS; + } + ctx->zone_count++; int ret; @@ -824,6 +852,11 @@ static int zone_txn_begin(zone_t *zone, _unused_ ctl_args_t *args) return KNOT_TXN_EEXISTS; } + if (zone->backup_ctx != NULL && zone->backup_ctx->restore_mode) { + log_zone_warning(zone->name, "zone restore pending, try opening control transaction later"); + return KNOT_EAGAIN; + } + zone->control_update = malloc(sizeof(zone_update_t)); if (zone->control_update == NULL) { return KNOT_ENOMEM; diff --git a/src/knot/dnssec/context.c b/src/knot/dnssec/context.c index 3413dba..c10e5c6 100644 --- a/src/knot/dnssec/context.c +++ b/src/knot/dnssec/context.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ #include "knot/dnssec/kasp/keystore.h" #include "knot/dnssec/key_records.h" #include "knot/server/dthreads.h" +#include "knot/zone/serial.h" knot_dynarray_define(parent, knot_kasp_parent_t, DYNARRAY_VISIBILITY_NORMAL) @@ -168,6 +169,13 @@ static void policy_load(knot_kasp_policy_t *policy, conf_t *conf, conf_val_t *id policy->unsafe |= conf_opt(&val); conf_val_next(&val); } + + val = conf_id_get(conf, C_POLICY, C_KEYTAG_MODULO, id); + int ret = serial_modulo_parse(conf_str(&val), &policy->keytag_remain, + &policy->keytag_modulo); + if (ret != KNOT_EOK) { + assert(0); // cannot happen - ensured by conf check + } } int kdnssec_ctx_init(conf_t *conf, kdnssec_ctx_t *ctx, const knot_dname_t *zone_name, diff --git a/src/knot/dnssec/ds_query.c b/src/knot/dnssec/ds_query.c index 375bb50..2ac91cc 100644 --- a/src/knot/dnssec/ds_query.c +++ b/src/knot/dnssec/ds_query.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,9 +27,9 @@ #include "knot/server/server.h" #define DS_CHECK_LOG(priority, zone, remote, flags, fmt, ...) \ - ns_log(priority, zone, LOG_OPERATION_DS_CHECK, LOG_DIRECTION_OUT, remote, \ + ns_log(priority, zone, LOG_OPERATION_DS_CHECK, LOG_DIRECTION_OUT, &(remote)->addr, \ ((flags) & KNOT_REQUESTOR_QUIC) ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP, \ - ((flags) & KNOT_REQUESTOR_REUSED), fmt, ## __VA_ARGS__) + ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, fmt, ## __VA_ARGS__) static bool match_key_ds(knot_kasp_key_t *key, knot_rdata_t *ds) { @@ -72,7 +72,7 @@ struct ds_query_data { conf_t *conf; const knot_dname_t *zone_name; - const struct sockaddr *remote; + const conf_remote_t *remote; knot_kasp_key_t *key; knot_kasp_key_t *not_key; @@ -116,8 +116,8 @@ static int ds_query_consume(knot_layer_t *layer, knot_pkt_t *pkt) uint16_t rcode = knot_pkt_ext_rcode(pkt); if (rcode != KNOT_RCODE_NOERROR) { DS_CHECK_LOG((rcode == KNOT_RCODE_NXDOMAIN ? LOG_NOTICE : LOG_WARNING), - data->zone_name, data->remote, layer->flags, - "failed (%s)", knot_pkt_ext_rcode_name(pkt)); + data->zone_name, data->remote, layer->flags, + "failed (%s)", knot_pkt_ext_rcode_name(pkt)); return KNOT_STATE_FAIL; } @@ -179,7 +179,7 @@ static int try_ds(conf_t *conf, const knot_dname_t *zone_name, const conf_remote struct ds_query_data data = { .zone_name = zone_name, - .remote = (struct sockaddr *)&parent->addr, + .remote = parent, .key = key, .not_key = not_key, .edns = query_edns_data_init(conf, parent, QUERY_EDNS_OPT_DO), @@ -214,7 +214,7 @@ static int try_ds(conf_t *conf, const knot_dname_t *zone_name, const conf_remote if (ret != KNOT_EOK && !data.result_logged) { DS_CHECK_LOG(LOG_WARNING, zone_name, data.remote, requestor.layer.flags, - "failed (%s)", knot_strerror(ret)); + "failed (%s)", knot_strerror(ret)); } *ds_ttl = data.ttl; diff --git a/src/knot/dnssec/kasp/policy.h b/src/knot/dnssec/kasp/policy.h index b70ac6c..d895d48 100644 --- a/src/knot/dnssec/kasp/policy.h +++ b/src/knot/dnssec/kasp/policy.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -132,5 +132,7 @@ typedef struct { bool incremental; bool key_label; unsigned unsafe; + uint32_t keytag_remain; + uint32_t keytag_modulo; } knot_kasp_policy_t; // TODO make the time parameters knot_timediff_t ?? diff --git a/src/knot/dnssec/zone-events.c b/src/knot/dnssec/zone-events.c index f2f6d93..faf093d 100644 --- a/src/knot/dnssec/zone-events.c +++ b/src/knot/dnssec/zone-events.c @@ -191,6 +191,9 @@ int knot_dnssec_zone_sign(zone_update_t *update, ctx.rrsig_drop_existing = flags & ZONE_SIGN_DROP_SIGNATURES; + // create placeholder ZONEMD to be signed and later filled in + // ...or remove it if zonemd_alg == ZONE_DIGEST_REMOVE + // removing non-existent ZONEMD is ok conf_val_t val = conf_zone_get(conf, C_ZONEMD_GENERATE, zone_name); unsigned zonemd_alg = conf_opt(&val); if (zonemd_alg != ZONE_DIGEST_NONE) { @@ -285,7 +288,9 @@ int knot_dnssec_zone_sign(zone_update_t *update, } } - if (zonemd_alg != ZONE_DIGEST_NONE) { + // fill in ZONEMD if desired + // if (zonemd_alg == ZONE_DIGEST_REMOVE), ZONEMD was already removed above, so skip this + if (zonemd_alg != ZONE_DIGEST_NONE && zonemd_alg != ZONE_DIGEST_REMOVE) { result = zone_update_add_digest(update, zonemd_alg, false); if (result == KNOT_EOK) { result = knot_zone_sign_apex_rr(update, KNOT_RRTYPE_ZONEMD, &keyset, &ctx); @@ -335,6 +340,9 @@ int knot_dnssec_sign_update(zone_update_t *update, conf_t *conf) update_policy_from_zone(ctx.policy, update->new_cont); + // create placeholder ZONEMD to be signed and later filled in + // ...or remove it & its RRSIGs if zonemd_alg == ZONE_DIGEST_REMOVE + // removing non-existent ZONEMD is ok conf_val_t val = conf_zone_get(conf, C_ZONEMD_GENERATE, zone_name); unsigned zonemd_alg = conf_opt(&val); if (zonemd_alg != ZONE_DIGEST_NONE) { @@ -412,7 +420,9 @@ int knot_dnssec_sign_update(zone_update_t *update, conf_t *conf) goto done; } - if (zonemd_alg != ZONE_DIGEST_NONE) { + // fill in ZONEMD if desired + // if (zonemd_alg == ZONE_DIGEST_REMOVE), ZONEMD was already removed above, so skip this + if (zonemd_alg != ZONE_DIGEST_NONE && zonemd_alg != ZONE_DIGEST_REMOVE) { result = zone_update_add_digest(update, zonemd_alg, false); if (result == KNOT_EOK) { result = knot_zone_sign_apex_rr(update, KNOT_RRTYPE_ZONEMD, &keyset, &ctx); diff --git a/src/knot/dnssec/zone-keys.c b/src/knot/dnssec/zone-keys.c index af8226c..05faac8 100644 --- a/src/knot/dnssec/zone-keys.c +++ b/src/knot/dnssec/zone-keys.c @@ -104,7 +104,7 @@ static bool keytag_in_use(kdnssec_ctx_t *ctx, uint16_t keytag) return false; } -#define GENERATE_KEYTAG_ATTEMPTS (20) +#define GENERATE_KEYTAG_ATTEMPTS (40) static int generate_keytag_unconflict(kdnssec_ctx_t *ctx, kdnssec_generate_flags_t flags, @@ -131,7 +131,9 @@ static int generate_keytag_unconflict(kdnssec_ctx_t *ctx, if (ret != KNOT_EOK) { return ret; } - if (!keytag_in_use(ctx, dnssec_key_get_keytag(*key))) { + uint16_t keytag = dnssec_key_get_keytag(*key); + if (!keytag_in_use(ctx, keytag) && + keytag % ctx->policy->keytag_modulo == ctx->policy->keytag_remain) { return KNOT_EOK; } diff --git a/src/knot/events/handlers/dnskey_sync.c b/src/knot/events/handlers/dnskey_sync.c index 8e6d823..c6d80ff 100644 --- a/src/knot/events/handlers/dnskey_sync.c +++ b/src/knot/events/handlers/dnskey_sync.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,9 +25,9 @@ #include "libknot/errcode.h" #define DNSKEY_SYNC_LOG(priority, zone, remote, flags, fmt, ...) \ - ns_log(priority, zone, LOG_OPERATION_DNSKEY_SYNC, LOG_DIRECTION_OUT, remote, \ + ns_log(priority, zone, LOG_OPERATION_DNSKEY_SYNC, LOG_DIRECTION_OUT, &(remote)->addr, \ ((flags) & KNOT_REQUESTOR_QUIC) ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP, \ - ((flags) & KNOT_REQUESTOR_REUSED), fmt, ## __VA_ARGS__) + ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, fmt, ## __VA_ARGS__) static const unsigned remote_rrs[] = { KNOT_RRTYPE_DNSKEY, KNOT_RRTYPE_CDNSKEY, KNOT_RRTYPE_CDS }; #define REMOTE_NTYPES (sizeof(remote_rrs) / sizeof(remote_rrs[0])) @@ -36,7 +36,7 @@ struct dnskey_sync_data { zone_t *zone; knot_rrset_t *rem_rr[REMOTE_NTYPES]; knot_rrset_t *add_rr[REMOTE_NTYPES]; - const struct sockaddr *remote; + const conf_remote_t *remote; query_edns_data_t edns; bool uptodate; bool ddns_sent; @@ -235,7 +235,7 @@ static int send_dnskey_sync(conf_t *conf, zone_t *zone, bool *uptodate, { struct dnskey_sync_data data = { .zone = zone, - .remote = (struct sockaddr *)&remote->addr, + .remote = remote, .edns = query_edns_data_init(conf, remote, 0) }; @@ -264,14 +264,14 @@ static int send_dnskey_sync(conf_t *conf, zone_t *zone, bool *uptodate, } if (data.ddns_sent && ret == KNOT_ETIMEOUT) { - DNSKEY_SYNC_LOG(LOG_WARNING, zone->name, &remote->addr, requestor.layer.flags, + DNSKEY_SYNC_LOG(LOG_WARNING, zone->name, remote, requestor.layer.flags, "timed out, may be caused by parallel mutual DNSKEY sync, " "may settle down after check-interval"); ret = KNOT_EOK; } if (ret != KNOT_EOK) { - DNSKEY_SYNC_LOG(LOG_ERR, zone->name, &remote->addr, requestor.layer.flags, + DNSKEY_SYNC_LOG(LOG_ERR, zone->name, remote, requestor.layer.flags, "failed (%s)", knot_strerror(ret)); } diff --git a/src/knot/events/handlers/ds_push.c b/src/knot/events/handlers/ds_push.c index 5a3a9bb..be7621f 100644 --- a/src/knot/events/handlers/ds_push.c +++ b/src/knot/events/handlers/ds_push.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,16 +30,16 @@ struct ds_push_data { knot_dname_t *parent_soa; knot_rrset_t del_old_ds; knot_rrset_t new_ds; - const struct sockaddr *remote; + const conf_remote_t *remote; query_edns_data_t edns; }; #define DS_PUSH_RETRY 600 #define DS_PUSH_LOG(priority, zone, remote, flags, fmt, ...) \ - ns_log(priority, zone, LOG_OPERATION_DS_PUSH, LOG_DIRECTION_OUT, remote, \ + ns_log(priority, zone, LOG_OPERATION_DS_PUSH, LOG_DIRECTION_OUT, &(remote)->addr, \ ((flags) & KNOT_REQUESTOR_QUIC) ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP, \ - ((flags) & KNOT_REQUESTOR_REUSED), fmt, ## __VA_ARGS__) + ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, fmt, ## __VA_ARGS__) static const knot_rdata_t remove_cds = { 5, { 0, 0, 0, 0, 0 } }; @@ -172,7 +172,7 @@ static int send_ds_push(conf_t *conf, zone_t *zone, .zone = zone->name, .parent_query = zone->name, .new_ds = zone_cds, - .remote = (struct sockaddr *)&parent->addr, + .remote = parent, .edns = query_edns_data_init(conf, parent, 0) }; @@ -203,13 +203,13 @@ static int send_ds_push(conf_t *conf, zone_t *zone, ret = knot_requestor_exec(&requestor, req, timeout); if (ret == KNOT_EOK && knot_pkt_ext_rcode(req->resp) == 0) { - DS_PUSH_LOG(LOG_INFO, zone->name, &parent->addr, requestor.layer.flags, + DS_PUSH_LOG(LOG_INFO, zone->name, parent, requestor.layer.flags, "success"); } else if (knot_pkt_ext_rcode(req->resp) == 0) { - DS_PUSH_LOG(LOG_WARNING, zone->name, &parent->addr, requestor.layer.flags, + DS_PUSH_LOG(LOG_WARNING, zone->name, parent, requestor.layer.flags, "failed (%s)", knot_strerror(ret)); } else { - DS_PUSH_LOG(LOG_WARNING, zone->name, &parent->addr, requestor.layer.flags, + DS_PUSH_LOG(LOG_WARNING, zone->name, parent, requestor.layer.flags, "server responded with error '%s'", knot_pkt_ext_rcode_name(req->resp)); } diff --git a/src/knot/events/handlers/notify.c b/src/knot/events/handlers/notify.c index ccddf88..9dae70a 100644 --- a/src/knot/events/handlers/notify.c +++ b/src/knot/events/handlers/notify.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,6 +15,7 @@ */ #include <assert.h> +#include <urcu.h> #include "contrib/openbsd/siphash.h" #include "knot/common/log.h" @@ -40,7 +41,7 @@ static notifailed_rmt_hash notifailed_hash(conf_val_t *rmt_id) struct notify_data { const knot_dname_t *zone; const knot_rrset_t *soa; - const struct sockaddr *remote; + const conf_remote_t *remote; query_edns_data_t edns; }; @@ -82,9 +83,9 @@ static const knot_layer_api_t NOTIFY_API = { }; #define NOTIFY_OUT_LOG(priority, zone, remote, flags, fmt, ...) \ - ns_log(priority, zone, LOG_OPERATION_NOTIFY, LOG_DIRECTION_OUT, remote, \ + ns_log(priority, zone, LOG_OPERATION_NOTIFY, LOG_DIRECTION_OUT, &(remote)->addr, \ ((flags) & KNOT_REQUESTOR_QUIC) ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP, \ - ((flags) & KNOT_REQUESTOR_REUSED), fmt, ## __VA_ARGS__) + ((flags) & KNOT_REQUESTOR_REUSED), (remote)->key.name, fmt, ## __VA_ARGS__) static int send_notify(conf_t *conf, zone_t *zone, const knot_rrset_t *soa, const conf_remote_t *slave, int timeout, bool retry) @@ -92,7 +93,7 @@ static int send_notify(conf_t *conf, zone_t *zone, const knot_rrset_t *soa, struct notify_data data = { .zone = zone->name, .soa = soa, - .remote = (struct sockaddr *)&slave->addr, + .remote = slave, .edns = query_edns_data_init(conf, slave, 0) }; @@ -118,16 +119,16 @@ static int send_notify(conf_t *conf, zone_t *zone, const knot_rrset_t *soa, const char *log_retry = retry ? "retry, " : ""; if (ret == KNOT_EOK && knot_pkt_ext_rcode(req->resp) == 0) { - NOTIFY_OUT_LOG(LOG_INFO, zone->name, &slave->addr, + NOTIFY_OUT_LOG(LOG_INFO, zone->name, slave, requestor.layer.flags, "%sserial %u", log_retry, knot_soa_serial(soa->rrs.rdata)); zone->timers.last_notified_serial = (knot_soa_serial(soa->rrs.rdata) | LAST_NOTIFIED_SERIAL_VALID); } else if (knot_pkt_ext_rcode(req->resp) == 0) { - NOTIFY_OUT_LOG(LOG_WARNING, zone->name, &slave->addr, + NOTIFY_OUT_LOG(LOG_WARNING, zone->name, slave, requestor.layer.flags, "%sfailed (%s)", log_retry, knot_strerror(ret)); } else { - NOTIFY_OUT_LOG(LOG_WARNING, zone->name, &slave->addr, + NOTIFY_OUT_LOG(LOG_WARNING, zone->name, slave, requestor.layer.flags, "%sserver responded with error '%s'", log_retry, knot_pkt_ext_rcode_name(req->resp)); @@ -151,7 +152,13 @@ int event_notify(conf_t *conf, zone_t *zone) // NOTIFY content int timeout = conf->cache.srv_tcp_remote_io_timeout; + rcu_read_lock(); knot_rrset_t soa = node_rrset(zone->contents->apex, KNOT_RRTYPE_SOA); + knot_rrset_t *soa_cpy = knot_rrset_copy(&soa, NULL); + rcu_read_unlock(); + if (soa_cpy == NULL) { + return KNOT_ENOMEM; + } // in case of re-try, NOTIFY only failed remotes pthread_mutex_lock(&zone->preferred_lock); @@ -176,7 +183,7 @@ int event_notify(conf_t *conf, zone_t *zone) for (int i = 0; i < addr_count; i++) { conf_remote_t slave = conf_remote(conf, iter.id, i); - ret = send_notify(conf, zone, &soa, &slave, timeout, retry); + ret = send_notify(conf, zone, soa_cpy, &slave, timeout, retry); if (ret == KNOT_EOK) { break; } @@ -196,7 +203,7 @@ int event_notify(conf_t *conf, zone_t *zone) if (failed) { notifailed_rmt_dynarray_sort_dedup(&zone->notifailed); - uint32_t retry_in = knot_soa_retry(soa.rrs.rdata); + uint32_t retry_in = knot_soa_retry(soa_cpy->rrs.rdata); conf_val_t val = conf_zone_get(conf, C_RETRY_MIN_INTERVAL, zone->name); retry_in = MAX(retry_in, conf_int(&val)); val = conf_zone_get(conf, C_RETRY_MAX_INTERVAL, zone->name); @@ -205,6 +212,7 @@ int event_notify(conf_t *conf, zone_t *zone) zone_events_schedule_at(zone, ZONE_EVENT_NOTIFY, time(NULL) + retry_in); } pthread_mutex_unlock(&zone->preferred_lock); + knot_rrset_free(soa_cpy, NULL); return failed ? KNOT_ERROR : KNOT_EOK; } diff --git a/src/knot/events/handlers/refresh.c b/src/knot/events/handlers/refresh.c index 32ee68d..83fb376 100644 --- a/src/knot/events/handlers/refresh.c +++ b/src/knot/events/handlers/refresh.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -72,15 +72,15 @@ #define REFRESH_LOG(priority, data, msg...) \ ns_log(priority, (data)->zone->name, LOG_OPERATION_REFRESH, LOG_DIRECTION_NONE, \ - (data)->remote, 0, false, msg) + &(data)->remote->addr, 0, false, (data)->remote->key.name, msg) #define AXFRIN_LOG(priority, data, msg...) \ ns_log(priority, (data)->zone->name, LOG_OPERATION_AXFR, LOG_DIRECTION_IN, \ - (data)->remote, PROTO(data), (data)->layer->flags & KNOT_REQUESTOR_REUSED, msg) + &(data)->remote->addr, PROTO(data), (data)->layer->flags & KNOT_REQUESTOR_REUSED, (data)->remote->key.name, msg) #define IXFRIN_LOG(priority, data, msg...) \ ns_log(priority, (data)->zone->name, LOG_OPERATION_IXFR, LOG_DIRECTION_IN, \ - (data)->remote, PROTO(data), (data)->layer->flags & KNOT_REQUESTOR_REUSED, msg) + &(data)->remote->addr, PROTO(data), (data)->layer->flags & KNOT_REQUESTOR_REUSED, (data)->remote->key.name, msg) enum state { REFRESH_STATE_INVALID = 0, @@ -104,7 +104,7 @@ struct refresh_data { zone_t *zone; //!< Zone to eventually updated. conf_t *conf; //!< Server configuration. - const struct sockaddr *remote; //!< Remote endpoint. + const conf_remote_t *remote; //!< Remote endpoint. const knot_rrset_t *soa; //!< Local SOA (NULL for AXFR). const size_t max_zone_size; //!< Maximal zone size. query_edns_data_t edns; //!< EDNS data to be used in queries. @@ -1196,10 +1196,10 @@ static int transfer_consume(knot_layer_t *layer, knot_pkt_t *pkt) data->xfr_type == XFR_TYPE_IXFR || data->xfr_type == XFR_TYPE_UPTODATE ? LOG_OPERATION_IXFR : LOG_OPERATION_AXFR, - LOG_DIRECTION_IN, data->remote, + LOG_DIRECTION_IN, &data->remote->addr, (layer->flags & KNOT_REQUESTOR_QUIC ? KNOTD_QUERY_PROTO_QUIC : KNOTD_QUERY_PROTO_TCP), - &data->stats); + data->remote->key.name, &data->stats); /* * TODO: Move finialization into finish @@ -1340,7 +1340,7 @@ static int try_refresh(conf_t *conf, zone_t *zone, const conf_remote_t *master, struct refresh_data data = { .zone = zone, .conf = conf, - .remote = (struct sockaddr *)&master->addr, + .remote = master, .soa = zone->contents && !trctx->force_axfr ? &soa : NULL, .max_zone_size = max_zone_size(conf, zone->name), .edns = query_edns_data_init(conf, master, QUERY_EDNS_OPT_EXPIRE), diff --git a/src/knot/events/handlers/update.c b/src/knot/events/handlers/update.c index b868273..b4092a3 100644 --- a/src/knot/events/handlers/update.c +++ b/src/knot/events/handlers/update.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,8 +33,8 @@ #define UPDATE_LOG(priority, qdata, fmt...) \ ns_log(priority, knot_pkt_qname(qdata->query), LOG_OPERATION_UPDATE, \ - LOG_DIRECTION_IN, (struct sockaddr *)knotd_qdata_remote_addr(qdata), \ - qdata->params->proto, false, fmt) + LOG_DIRECTION_IN, (qdata)->params->remote, \ + (qdata)->params->proto, false, (qdata)->sign.tsig_key.name, fmt) static void init_qdata_from_request(knotd_qdata_t *qdata, zone_t *zone, diff --git a/src/knot/modules/authsignal/authsignal.rst b/src/knot/modules/authsignal/authsignal.rst index 01043a1..d3a52ad 100644 --- a/src/knot/modules/authsignal/authsignal.rst +++ b/src/knot/modules/authsignal/authsignal.rst @@ -18,6 +18,7 @@ Automatic forward records ......................... :: + mod-onlinesign: - id: authsignal nsec-bitmap: [CDS, CDNSKEY] diff --git a/src/knot/modules/dnstap/dnstap.c b/src/knot/modules/dnstap/dnstap.c index c8c82ea..612e488 100644 --- a/src/knot/modules/dnstap/dnstap.c +++ b/src/knot/modules/dnstap/dnstap.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -185,6 +185,33 @@ finish: return writer; } +static struct fstrm_writer* dnstap_tcp_writer(const char *address, const char *port) +{ + struct fstrm_tcp_writer_options *opt = NULL; + struct fstrm_writer_options *wopt = NULL; + struct fstrm_writer *writer = NULL; + + opt = fstrm_tcp_writer_options_init(); + if (opt == NULL) { + goto finish; + } + + fstrm_tcp_writer_options_set_socket_address(opt, address); + fstrm_tcp_writer_options_set_socket_port(opt, port); + + wopt = fstrm_writer_options_init(); + if (wopt == NULL) { + goto finish; + } + fstrm_writer_options_add_content_type(wopt, DNSTAP_CONTENT_TYPE, + strlen(DNSTAP_CONTENT_TYPE)); + writer = fstrm_tcp_writer_init(opt, wopt); +finish: + fstrm_tcp_writer_options_destroy(&opt); + fstrm_writer_options_destroy(&wopt); + return writer; +} + /*! \brief Create a basic file writer sink. */ static struct fstrm_writer* dnstap_file_writer(const char *path) { @@ -213,17 +240,42 @@ finish: } /*! \brief Create a log sink according to the path string. */ -static struct fstrm_writer* dnstap_writer(const char *path) +static struct fstrm_writer* dnstap_writer(knotd_mod_t *mod, const char *path) { - const char *prefix = "unix:"; - const size_t prefix_len = strlen(prefix); + const char *unix_prefix = "unix:"; + const size_t unix_prefix_len = strlen(unix_prefix); + + const char *tcp_prefix = "tcp:"; + const size_t tcp_prefix_len = strlen(tcp_prefix); + + const size_t path_len = strlen(path); /* UNIX socket prefix. */ - if (strlen(path) > prefix_len && strncmp(path, prefix, prefix_len) == 0) { - return dnstap_unix_writer(path + prefix_len); + if (path_len > unix_prefix_len && + strncmp(path, unix_prefix, unix_prefix_len) == 0) { + knotd_mod_log(mod, LOG_DEBUG, "using sink UNIX socket '%s'", path); + return dnstap_unix_writer(path + unix_prefix_len); + /* TCP socket prefix. */ + } else if (path_len > tcp_prefix_len && + strncmp(path, tcp_prefix, tcp_prefix_len) == 0) { + char addr[INET6_ADDRSTRLEN] = { 0 }; + const char *delimiter = strchr(path + tcp_prefix_len, '@'); + if (delimiter == NULL) { + return NULL; + } + size_t addr_len = delimiter - path - tcp_prefix_len; + if (addr_len >= sizeof(addr)) { + return NULL; + } + memcpy(addr, path + tcp_prefix_len, addr_len); + knotd_mod_log(mod, LOG_DEBUG, "using sink TCP address '%s' port '%s'", + addr, delimiter + 1); + return dnstap_tcp_writer(addr, delimiter + 1); + /* File path. */ + } else { + knotd_mod_log(mod, LOG_DEBUG, "using sink file '%s'", path); + return dnstap_file_writer(path); } - - return dnstap_file_writer(path); } int dnstap_load(knotd_mod_t *mod) @@ -273,7 +325,7 @@ int dnstap_load(knotd_mod_t *mod) const bool log_responses = conf.single.boolean; /* Initialize the writer and the options. */ - struct fstrm_writer *writer = dnstap_writer(sink); + struct fstrm_writer *writer = dnstap_writer(mod, sink); if (writer == NULL) { goto fail; } @@ -307,13 +359,13 @@ int dnstap_load(knotd_mod_t *mod) return KNOT_EOK; fail: - knotd_mod_log(mod, LOG_ERR, "failed to init sink '%s'", sink); + knotd_mod_log(mod, LOG_ERR, "failed to initialize sink '%s'", sink); free(ctx->identity); free(ctx->version); free(ctx); - return KNOT_ENOMEM; + return KNOT_EINVAL; } void dnstap_unload(knotd_mod_t *mod) diff --git a/src/knot/modules/dnstap/dnstap.rst b/src/knot/modules/dnstap/dnstap.rst index 358977d..05eac09 100644 --- a/src/knot/modules/dnstap/dnstap.rst +++ b/src/knot/modules/dnstap/dnstap.rst @@ -11,7 +11,7 @@ Example ------- The configuration comprises only a :ref:`mod-dnstap_sink` path parameter, -which can be either a file or a UNIX socket:: +which can be either a file, a UNIX socket, or a TCP address:: mod-dnstap: - id: capture_all @@ -60,9 +60,10 @@ A module identifier. sink .... -A sink path, which can be either a file or a UNIX socket when prefixed with -``unix:``. The file may be specified as an absolute path or a path relative -to the :doc:`knotd<man_knotd>` startup directory. +A sink path, which can be either a file, a UNIX socket when prefixed with +``unix:``, or a TCP `address@port` when prefixed with ``tcp:``. The file may +be specified as an absolute path or a path relative to +the :doc:`knotd<man_knotd>` startup directory. *Required* diff --git a/src/knot/nameserver/axfr.c b/src/knot/nameserver/axfr.c index 677e241..dcd62e9 100644 --- a/src/knot/nameserver/axfr.c +++ b/src/knot/nameserver/axfr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,12 +25,13 @@ #include "libknot/libknot.h" #define ZONE_NAME(qdata) knot_pkt_qname((qdata)->query) -#define REMOTE(qdata) (struct sockaddr *)knotd_qdata_remote_addr(qdata) +#define REMOTE(qdata) (qdata)->params->remote #define PROTO(qdata) (qdata)->params->proto +#define KEY(qdata) (qdata)->sign.tsig_key.name #define AXFROUT_LOG(priority, qdata, fmt...) \ ns_log(priority, ZONE_NAME(qdata), LOG_OPERATION_AXFR, \ - LOG_DIRECTION_OUT, REMOTE(qdata), PROTO(qdata), false, fmt) + LOG_DIRECTION_OUT, REMOTE(qdata), PROTO(qdata), false, KEY(qdata), fmt) /* AXFR context. @note aliasing the generic xfr_proc */ struct axfr_proc { @@ -120,7 +121,7 @@ static void axfr_answer_finished(knotd_qdata_t *qdata, knot_pkt_t *pkt, int stat xfr_stats_add(&xfr->stats, pkt->size); xfr_stats_end(&xfr->stats); xfr_log_finished(ZONE_NAME(qdata), LOG_OPERATION_AXFR, LOG_DIRECTION_OUT, - REMOTE(qdata), PROTO(qdata), &xfr->stats); + REMOTE(qdata), PROTO(qdata), KEY(qdata), &xfr->stats); break; default: break; diff --git a/src/knot/nameserver/ixfr.c b/src/knot/nameserver/ixfr.c index ea15273..b57759c 100644 --- a/src/knot/nameserver/ixfr.c +++ b/src/knot/nameserver/ixfr.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,12 +28,13 @@ #include "libknot/libknot.h" #define ZONE_NAME(qdata) knot_pkt_qname((qdata)->query) -#define REMOTE(qdata) (struct sockaddr *)knotd_qdata_remote_addr(qdata) +#define REMOTE(qdata) (qdata)->params->remote #define PROTO(qdata) (qdata)->params->proto +#define KEY(qdata) (qdata)->sign.tsig_key.name #define IXFROUT_LOG(priority, qdata, fmt...) \ ns_log(priority, ZONE_NAME(qdata), LOG_OPERATION_IXFR, \ - LOG_DIRECTION_OUT, REMOTE(qdata), PROTO(qdata), false, fmt) + LOG_DIRECTION_OUT, REMOTE(qdata), PROTO(qdata), false, KEY(qdata), fmt) /*! \brief Helper macro for putting RRs into packet. */ #define IXFR_SAFE_PUT(pkt, rr) \ @@ -173,7 +174,7 @@ static void ixfr_answer_finished(knotd_qdata_t *qdata, knot_pkt_t *pkt, int stat xfr_stats_add(&xfr->stats, pkt->size); xfr_stats_end(&xfr->stats); xfr_log_finished(ZONE_NAME(qdata), LOG_OPERATION_IXFR, LOG_DIRECTION_OUT, - REMOTE(qdata), PROTO(qdata), &xfr->stats); + REMOTE(qdata), PROTO(qdata), KEY(qdata), &xfr->stats); break; default: break; diff --git a/src/knot/nameserver/log.h b/src/knot/nameserver/log.h index 752de55..5a5d5f0 100644 --- a/src/knot/nameserver/log.h +++ b/src/knot/nameserver/log.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -88,16 +88,16 @@ static inline const char *log_conn_info(knotd_query_proto_t proto, bool pool) /*! * \brief Generate log message for server communication. - * - * Example output: - * - * [example.com] NOTIFY, outgoing, remote 2001:db8::1@53, serial 123 */ -#define ns_log(priority, zone, op, dir, remote, proto, pool, fmt, ...) \ +#define ns_log(priority, zone, op, dir, remote, proto, pool, key, fmt, ...) \ do { \ + knot_dname_txt_storage_t key_str; \ char address[SOCKADDR_STRLEN] = ""; \ - sockaddr_tostr(address, sizeof(address), (const struct sockaddr_storage *)remote); \ - log_fmt_zone(priority, LOG_SOURCE_ZONE, zone, NULL, "%s%s, remote %s%s, " fmt, \ + sockaddr_tostr(address, sizeof(address), remote); \ + (void)knot_dname_to_str(key_str, key, sizeof(key_str)); \ + log_fmt_zone(priority, LOG_SOURCE_ZONE, zone, NULL, "%s%s, remote %s%s, %s%s%s" fmt, \ log_operation_name(op), log_direction_name(dir), address, \ - log_conn_info(proto, pool), ## __VA_ARGS__); \ + log_conn_info(proto, pool), (key != NULL ? "key " : ""), \ + (key != NULL ? key_str : ""), (key != NULL ? ", " : ""), \ + ## __VA_ARGS__); \ } while (0) diff --git a/src/knot/nameserver/notify.c b/src/knot/nameserver/notify.c index f5c5ee5..eaa305a 100644 --- a/src/knot/nameserver/notify.c +++ b/src/knot/nameserver/notify.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,8 +26,8 @@ #define NOTIFY_IN_LOG(priority, qdata, fmt...) \ ns_log(priority, knot_pkt_qname(qdata->query), LOG_OPERATION_NOTIFY, \ - LOG_DIRECTION_IN, knotd_qdata_remote_addr(qdata), qdata->params->proto, \ - false, fmt) + LOG_DIRECTION_IN, (qdata)->params->remote, (qdata)->params->proto, \ + false, (qdata)->sign.tsig_key.name, fmt) static int notify_check_query(knotd_qdata_t *qdata) { diff --git a/src/knot/nameserver/xfr.h b/src/knot/nameserver/xfr.h index 94a5621..e6d06b6 100644 --- a/src/knot/nameserver/xfr.h +++ b/src/knot/nameserver/xfr.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,10 +36,11 @@ void xfr_stats_end(struct xfr_stats *stats); static inline void xfr_log_finished(const knot_dname_t *zone, log_operation_t op, - log_direction_t dir, const struct sockaddr *remote, - knotd_query_proto_t proto, const struct xfr_stats *stats) + log_direction_t dir, const struct sockaddr_storage *remote, + knotd_query_proto_t proto, const knot_dname_t *key_name, + const struct xfr_stats *stats) { - ns_log(LOG_INFO, zone, op, dir, remote, proto, false, + ns_log(LOG_INFO, zone, op, dir, remote, proto, false, key_name, "%sfinished, %0.2f seconds, %u messages, %u bytes", (proto == KNOTD_QUERY_PROTO_QUIC && dir == LOG_DIRECTION_OUT ? "buffering " : ""), time_diff_ms(&stats->begin, &stats->end) / 1000.0, diff --git a/src/knot/server/xdp-handler.c b/src/knot/server/xdp-handler.c index 11eeeb6..ae8512d 100644 --- a/src/knot/server/xdp-handler.c +++ b/src/knot/server/xdp-handler.c @@ -83,6 +83,20 @@ void xdp_handle_reconfigure(xdp_handle_ctx_t *ctx) void xdp_handle_free(xdp_handle_ctx_t *ctx) { + // send RST on all existing conns + knot_tcp_relay_t sweep_relays[XDP_BATCHLEN] = { 0 }; + int ret = KNOT_EOK; + while (ret == KNOT_EOK && ctx->tcp_table != NULL && ctx->tcp_table->usage > 0) { + knot_xdp_send_prepare(ctx->sock); + ret = knot_tcp_sweep(ctx->tcp_table, UINT32_MAX, 1, UINT32_MAX, UINT32_MAX, SIZE_MAX, + SIZE_MAX, sweep_relays, XDP_BATCHLEN, &ctx->tcp_closed); + if (ret == KNOT_EOK) { + ret = knot_tcp_send(ctx->sock, sweep_relays, XDP_BATCHLEN, XDP_BATCHLEN); + } + knot_tcp_cleanup(ctx->tcp_table, sweep_relays, XDP_BATCHLEN); + (void)knot_xdp_send_finish(ctx->sock); + } + knot_tcp_table_free(ctx->tcp_table); knot_tcp_table_free(ctx->syn_table); #ifdef ENABLE_QUIC diff --git a/src/knot/updates/zone-update.c b/src/knot/updates/zone-update.c index 64ce179..73c9558 100644 --- a/src/knot/updates/zone-update.c +++ b/src/knot/updates/zone-update.c @@ -979,7 +979,7 @@ int zone_update_commit(conf_t *conf, zone_update_t *update) return ret; } - if (dnssec && zone_is_slave(conf, update->zone)) { + if (dnssec) { ret = zone_set_lastsigned_serial(update->zone, zone_contents_serial(update->new_cont)); if (ret != KNOT_EOK) { diff --git a/src/knot/zone/backup.h b/src/knot/zone/backup.h index d3ae07d..9f2660d 100644 --- a/src/knot/zone/backup.h +++ b/src/knot/zone/backup.h @@ -49,6 +49,9 @@ typedef enum { #define BACKUP_PARAM_DFLT_R (BACKUP_PARAM_ZONEFILE | BACKUP_PARAM_TIMERS | \ BACKUP_PARAM_KASPDB | BACKUP_PARAM_CATALOG) +/*! \bref Empty defaults. */ +#define BACKUP_PARAM_EMPTY 0 + /*! \bref Backup components done in event. */ #define BACKUP_PARAM_EVENT (BACKUP_PARAM_ZONEFILE | BACKUP_PARAM_JOURNAL | \ BACKUP_PARAM_TIMERS | BACKUP_PARAM_KASPDB | \ diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c index d0fbde4..6bdfb1d 100644 --- a/src/knot/zone/zone.c +++ b/src/knot/zone/zone.c @@ -704,7 +704,7 @@ int zone_master_try(conf_t *conf, zone_t *zone, zone_master_cb callback, true, true, preferred_idx == last_idx, pin_tolerance }; ret = try_remote(conf, zone, callback, callback_data, err_str, - preferred_id, &preferred, &fallback, "notifying "); + preferred_id, &preferred, &fallback, "notifier "); if (ret == KNOT_EOK || !fallback.remote) { return ret; // Success or local error. } diff --git a/src/libdnssec/version.h b/src/libdnssec/version.h index 0368f18..ad691c7 100644 --- a/src/libdnssec/version.h +++ b/src/libdnssec/version.h @@ -18,7 +18,7 @@ #define DNSSEC_VERSION_MAJOR 3 #define DNSSEC_VERSION_MINOR 3 -#define DNSSEC_VERSION_PATCH 0x05 +#define DNSSEC_VERSION_PATCH 0x06 #define DNSSEC_VERSION_HEX ((DNSSEC_VERSION_MAJOR << 16) | \ (DNSSEC_VERSION_MINOR << 8) | \ diff --git a/src/libknot/control/control.c b/src/libknot/control/control.c index 8656057..671896f 100644 --- a/src/libknot/control/control.c +++ b/src/libknot/control/control.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,7 +37,7 @@ #endif /*! Listen backlog size. */ -#define LISTEN_BACKLOG 5 +#define DEFAULT_LISTEN_BACKLOG 5 /*! Default socket operations timeout in milliseconds. */ #define DEFAULT_TIMEOUT (30 * 1000) @@ -196,6 +196,12 @@ void knot_ctl_set_timeout(knot_ctl_t *ctx, int timeout_ms) _public_ int knot_ctl_bind(knot_ctl_t *ctx, const char *path) { + return knot_ctl_bind2(ctx, path, DEFAULT_LISTEN_BACKLOG); +} + +_public_ +int knot_ctl_bind2(knot_ctl_t *ctx, const char *path, unsigned backlog) +{ if (ctx == NULL || path == NULL) { return KNOT_EINVAL; } @@ -215,7 +221,7 @@ int knot_ctl_bind(knot_ctl_t *ctx, const char *path) } // Start listening. - if (listen(ctx->listen_sock, LISTEN_BACKLOG) != 0) { + if (listen(ctx->listen_sock, backlog) != 0) { close_sock(&ctx->listen_sock); return knot_map_errno(); } diff --git a/src/libknot/control/control.h b/src/libknot/control/control.h index 1d3dcd1..8ab1e10 100644 --- a/src/libknot/control/control.h +++ b/src/libknot/control/control.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -94,6 +94,11 @@ void knot_ctl_set_timeout(knot_ctl_t *ctx, int timeout_ms); int knot_ctl_bind(knot_ctl_t *ctx, const char *path); /*! + * Same as knot_ctl_bind() with socket backlog specification. + */ +int knot_ctl_bind2(knot_ctl_t *ctx, const char *path, unsigned backlog); + +/*! * Unbinds a control socket. * * \note Server operation. diff --git a/src/libknot/quic/quic.c b/src/libknot/quic/quic.c index 5e447e7..f9d1d1d 100644 --- a/src/libknot/quic/quic.c +++ b/src/libknot/quic/quic.c @@ -44,6 +44,7 @@ #include "libknot/wire.h" #define SERVER_DEFAULT_SCIDLEN 18 +#define QUIC_REGULAR_TOKEN_TIMEOUT (24 * 3600 * 1000000000LLU) #define QUIC_DEFAULT_VERSION "-VERS-ALL:+VERS-TLS1.3" #define QUIC_DEFAULT_GROUPS "-GROUP-ALL:+GROUP-X25519:+GROUP-SECP256R1:+GROUP-SECP384R1:+GROUP-SECP521R1" @@ -971,14 +972,25 @@ int knot_quic_handle(knot_quic_table_t *table, knot_quic_reply_t *reply, } if (header.tokenlen > 0) { - ret = ngtcp2_crypto_verify_retry_token( - &odcid, header.token, header.tokenlen, - (const uint8_t *)table->hash_secret, - sizeof(table->hash_secret), header.version, - (const struct sockaddr *)reply->ip_rem, - addr_len((struct sockaddr_in6 *)reply->ip_rem), - &dcid, idle_timeout, now // NOTE setting retry token validity to idle_timeout for simplicity - ); + if (header.token[0] == NGTCP2_CRYPTO_TOKEN_MAGIC_RETRY) { + ret = ngtcp2_crypto_verify_retry_token( + &odcid, header.token, header.tokenlen, + (const uint8_t *)table->hash_secret, + sizeof(table->hash_secret), header.version, + (const struct sockaddr *)reply->ip_rem, + addr_len((struct sockaddr_in6 *)reply->ip_rem), + &dcid, idle_timeout, now // NOTE setting retry token validity to idle_timeout for simplicity + ); + } else { + ret = ngtcp2_crypto_verify_regular_token( + header.token, header.tokenlen, + (const uint8_t *)table->hash_secret, + sizeof(table->hash_secret), + (const struct sockaddr *)reply->ip_rem, + addr_len((struct sockaddr_in6 *)reply->ip_rem), + QUIC_REGULAR_TOKEN_TIMEOUT, now + ); + } if (ret != 0) { ret = KNOT_EOK; goto finish; diff --git a/src/libknot/version.h b/src/libknot/version.h index 2f86ed7..66b1793 100644 --- a/src/libknot/version.h +++ b/src/libknot/version.h @@ -18,7 +18,7 @@ #define KNOT_VERSION_MAJOR 3 #define KNOT_VERSION_MINOR 3 -#define KNOT_VERSION_PATCH 0x05 +#define KNOT_VERSION_PATCH 0x06 #define KNOT_VERSION_HEX ((KNOT_VERSION_MAJOR << 16) | \ (KNOT_VERSION_MINOR << 8) | \ diff --git a/src/libknot/xdp/tcp.c b/src/libknot/xdp/tcp.c index 7d647d7..94d445c 100644 --- a/src/libknot/xdp/tcp.c +++ b/src/libknot/xdp/tcp.c @@ -588,7 +588,7 @@ int knot_tcp_send(knot_xdp_socket_t *socket, knot_tcp_relay_t relays[], break; case XDP_TCP_RESET: NEXT_MSG - msg->flags |= KNOT_XDP_MSG_RST; + msg->flags |= (KNOT_XDP_MSG_RST | KNOT_XDP_MSG_ACK); break; case XDP_TCP_NOOP: default: diff --git a/src/libknot/yparser/ypbody.c b/src/libknot/yparser/ypbody.c index ad9cf1f..3343604 100644 --- a/src/libknot/yparser/ypbody.c +++ b/src/libknot/yparser/ypbody.c @@ -1,5 +1,5 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,8 +45,8 @@ static const unsigned char _yparser_key_offsets[] = { 0, 0, 14, 16, 27, 29, 32, 43, 44, 54, 65, 67, 68, 78, 90, 94, 96, 99, 104, 107, 110, 122, 132, 142, - 145, 148, 151, 156, 159, 162, 176, 190, - 204 + 145, 155, 160, 163, 166, 169, 172, 186, + 200, 214 }; static const char _yparser_trans_keys[] = { @@ -65,43 +65,44 @@ static const char _yparser_trans_keys[] = { 34, 32, 126, 34, 92, 127, 0, 31, 10, 13, 32, 34, 32, 126, 10, 13, 32, 34, 35, 44, 91, 92, 93, 127, - 0, 31, 32, 34, 35, 44, 92, 127, - 0, 31, 91, 93, 32, 44, 91, 92, + 0, 31, 32, 34, 35, 44, 91, 92, + 93, 127, 0, 31, 32, 44, 91, 92, 93, 127, 0, 31, 34, 35, 32, 44, - 93, 10, 13, 32, 34, 32, 126, 34, - 92, 127, 0, 31, 32, 44, 93, 34, - 32, 126, 10, 13, 32, 35, 42, 45, + 93, 32, 34, 35, 44, 92, 127, 0, + 31, 91, 93, 34, 92, 127, 0, 31, + 32, 44, 93, 10, 13, 32, 34, 32, + 126, 34, 32, 126, 10, 13, 32, 35, + 42, 45, 92, 95, 46, 57, 65, 90, + 97, 122, 10, 13, 32, 35, 42, 45, 92, 95, 46, 57, 65, 90, 97, 122, 10, 13, 32, 35, 42, 45, 92, 95, 46, 57, 65, 90, 97, 122, 10, 13, 32, 35, 42, 45, 92, 95, 46, 57, - 65, 90, 97, 122, 10, 13, 32, 35, - 42, 45, 92, 95, 46, 57, 65, 90, - 97, 122, 0 + 65, 90, 97, 122, 0 }; static const char _yparser_single_lengths[] = { 0, 8, 2, 5, 2, 3, 5, 1, 4, 5, 2, 1, 6, 6, 4, 2, - 1, 3, 3, 1, 10, 6, 6, 3, - 3, 1, 3, 3, 1, 8, 8, 8, - 8 + 1, 3, 3, 1, 10, 8, 6, 3, + 6, 3, 3, 3, 1, 1, 8, 8, + 8, 8 }; static const char _yparser_range_lengths[] = { 0, 3, 0, 3, 0, 0, 3, 0, 3, 3, 0, 0, 2, 3, 0, 0, - 1, 1, 0, 1, 1, 2, 2, 0, - 0, 1, 1, 0, 1, 3, 3, 3, - 3 + 1, 1, 0, 1, 1, 1, 2, 0, + 2, 1, 0, 0, 1, 1, 3, 3, + 3, 3 }; static const unsigned char _yparser_index_offsets[] = { 0, 0, 12, 15, 24, 27, 31, 40, 42, 50, 59, 62, 64, 73, 83, 88, - 91, 94, 99, 103, 106, 118, 127, 136, - 140, 144, 147, 152, 156, 159, 171, 183, - 195 + 91, 94, 99, 103, 106, 118, 128, 137, + 141, 150, 155, 159, 163, 166, 169, 181, + 193, 205 }; static const char _yparser_indicies[] = { @@ -120,30 +121,32 @@ static const char _yparser_indicies[] = { 0, 0, 37, 30, 31, 32, 0, 40, 37, 0, 12, 13, 14, 27, 35, 0, 41, 28, 0, 0, 0, 26, 41, 43, - 0, 0, 44, 0, 0, 0, 42, 46, - 47, 0, 48, 49, 0, 0, 0, 45, - 50, 41, 51, 0, 12, 13, 34, 0, - 52, 45, 0, 54, 55, 0, 0, 53, - 46, 47, 49, 0, 56, 53, 0, 1, - 2, 3, 4, 57, 6, 57, 57, 57, - 57, 57, 0, 59, 60, 61, 62, 63, - 64, 63, 63, 63, 63, 63, 58, 65, - 66, 67, 68, 69, 70, 69, 69, 69, - 69, 69, 0, 71, 72, 73, 74, 75, - 76, 75, 75, 75, 75, 75, 58, 0 + 0, 0, 0, 44, 45, 0, 0, 42, + 47, 48, 0, 49, 50, 0, 0, 0, + 46, 51, 52, 45, 0, 52, 43, 0, + 0, 44, 0, 0, 0, 42, 54, 55, + 0, 0, 53, 47, 48, 50, 0, 12, + 13, 34, 0, 56, 53, 0, 57, 46, + 0, 1, 2, 3, 4, 58, 6, 58, + 58, 58, 58, 58, 0, 60, 61, 62, + 63, 64, 65, 64, 64, 64, 64, 64, + 59, 66, 67, 68, 69, 70, 71, 70, + 70, 70, 70, 70, 0, 72, 73, 74, + 75, 76, 77, 76, 76, 76, 76, 76, + 59, 0 }; static const char _yparser_trans_targs[] = { - 0, 30, 31, 1, 2, 3, 7, 4, - 3, 5, 4, 5, 32, 29, 20, 4, + 0, 31, 32, 1, 2, 3, 7, 4, + 3, 5, 4, 5, 33, 30, 20, 4, 6, 5, 8, 9, 10, 9, 11, 10, - 11, 12, 13, 17, 16, 13, 32, 29, + 11, 12, 13, 17, 16, 13, 33, 30, 14, 16, 14, 15, 13, 17, 18, 19, - 17, 21, 22, 26, 25, 22, 23, 21, - 25, 24, 23, 24, 22, 26, 27, 28, - 26, 6, 0, 30, 31, 1, 2, 6, - 7, 30, 31, 1, 2, 6, 7, 30, - 31, 1, 2, 6, 7 + 17, 21, 22, 25, 29, 27, 22, 23, + 24, 29, 27, 23, 24, 25, 26, 28, + 25, 22, 6, 0, 31, 32, 1, 2, + 6, 7, 31, 32, 1, 2, 6, 7, + 31, 32, 1, 2, 6, 7 }; static const char _yparser_trans_actions[] = { @@ -152,26 +155,26 @@ static const char _yparser_trans_actions[] = { 13, 15, 21, 46, 19, 13, 19, 0, 0, 0, 37, 7, 37, 9, 43, 11, 11, 9, 0, 0, 40, 9, 0, 9, - 40, 0, 37, 7, 37, 9, 11, 11, - 9, 11, 0, 0, 40, 9, 0, 9, - 40, 46, 31, 55, 28, 88, 28, 83, - 93, 34, 5, 75, 5, 71, 79, 25, - 3, 63, 3, 59, 67 + 40, 0, 37, 7, 37, 0, 9, 11, + 11, 9, 11, 0, 0, 9, 0, 9, + 40, 40, 46, 31, 55, 28, 88, 28, + 83, 93, 34, 5, 75, 5, 71, 79, + 25, 3, 63, 3, 59, 67 }; static const char _yparser_eof_actions[] = { 0, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 0, 28, 5, - 3 + 23, 23, 23, 23, 23, 23, 0, 28, + 5, 3 }; -int _yp_start_state = 29; +int _yp_start_state = 30; int _yp_parse( yp_parser_t *parser) diff --git a/src/libzscanner/version.h b/src/libzscanner/version.h index 25520c7..12d0d9e 100644 --- a/src/libzscanner/version.h +++ b/src/libzscanner/version.h @@ -18,7 +18,7 @@ #define ZSCANNER_VERSION_MAJOR 3 #define ZSCANNER_VERSION_MINOR 3 -#define ZSCANNER_VERSION_PATCH 0x05 +#define ZSCANNER_VERSION_PATCH 0x06 #define ZSCANNER_VERSION_HEX ((ZSCANNER_VERSION_MAJOR << 16) | \ (ZSCANNER_VERSION_MINOR << 8) | \ diff --git a/src/utils/common/params.c b/src/utils/common/params.c index 4db4b9e..d16af4c 100644 --- a/src/utils/common/params.c +++ b/src/utils/common/params.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -47,7 +47,12 @@ char *name_from_idn(const char *idn_name) { return NULL; } - return name; + if (strcasecmp(idn_name, name) == 0) { + free(name); + return strdup(idn_name); + } else { + return name; + } #endif return strdup(idn_name); } @@ -212,7 +217,7 @@ char *get_fqd_name(const char *name) size_t name_len = strlen(name); // If the name is FQDN, make a copy. - if (name[name_len - 1] == '.') { + if (name_len > 0 && name[name_len - 1] == '.') { fqd_name = strdup(name); // Else make a copy and append a trailing dot. } else { diff --git a/src/utils/common/quic.c b/src/utils/common/quic.c index 55e5408..704f3b1 100644 --- a/src/utils/common/quic.c +++ b/src/utils/common/quic.c @@ -564,6 +564,10 @@ int quic_ctx_connect(quic_ctx_t *ctx, int sockfd, struct addrinfo *dst_addr) ret = poll(&pfd, 1, timeout); if (ret == 0) { ret = ngtcp2_conn_handle_expiry(ctx->conn, quic_timestamp()); + if (ret != 0) { + WARN("QUIC, failed to send"); + return KNOT_ECONNABORTED; + } } else if (ret < 0) { return knot_map_errno(); } @@ -658,6 +662,10 @@ int quic_send_dns_query(quic_ctx_t *ctx, int sockfd, struct addrinfo *srv, return knot_map_errno(); } else if (ret == 0) { ret = ngtcp2_conn_handle_expiry(ctx->conn, quic_timestamp()); + if (ret != 0) { + WARN("QUIC, failed to send"); + return KNOT_ECONNABORTED; + } continue; } ret = quic_recv(ctx, sockfd); @@ -701,6 +709,10 @@ int quic_recv_dns_response(quic_ctx_t *ctx, uint8_t *buf, const size_t buf_len, return knot_map_errno(); } else if (ret == 0) { ret = ngtcp2_conn_handle_expiry(ctx->conn, quic_timestamp()); + if (ret != 0) { + WARN("QUIC, failed to send"); + return KNOT_ECONNABORTED; + } WARN("QUIC, peer took too long to respond"); goto send; } diff --git a/src/utils/kdig/kdig_params.c b/src/utils/kdig/kdig_params.c index 310e890..c8fd83f 100644 --- a/src/utils/kdig/kdig_params.c +++ b/src/utils/kdig/kdig_params.c @@ -1982,7 +1982,7 @@ static int parse_name(const char *value, list_t *queries, const query_t *conf) char *ascii_name = (char *)value; char *fqd_name = NULL; - if (value != NULL) { + if (value != NULL && value[0] != '\0') { if (conf->idn) { ascii_name = name_from_idn(value); if (ascii_name == NULL) { diff --git a/src/utils/knotc/commands.c b/src/utils/knotc/commands.c index e5cb455..c2c25a2 100644 --- a/src/utils/knotc/commands.c +++ b/src/utils/knotc/commands.c @@ -688,6 +688,7 @@ static int cmd_zone_ctl(cmd_args_t *args) } #define FILTER_IMPORT_NOPURGE "+nopurge" +#define FILTER_EXPORT_SCHEMA "+schema" typedef struct { const char *name; @@ -1173,22 +1174,45 @@ static int cmd_conf_import(cmd_args_t *args) static int cmd_conf_export(cmd_args_t *args) { - int ret = check_args(args, 0, 1); + int ret = check_args(args, 0, 2); if (ret != KNOT_EOK) { return ret; } // Stdout is the default output file. const char *file_name = NULL; - if (args->argc > 0) { - file_name = args->argv[0]; - log_debug("exporting confdb into file '%s'", file_name); + bool export_schema = false; + for (int i = 0; i < args->argc; i++) { + if (args->argv[i][0] == '+') { + if (strcmp(args->argv[i], FILTER_EXPORT_SCHEMA) == 0) { + export_schema = true; + } else { + log_error("unknown filter: %s", args->argv[i]); + return KNOT_EINVAL; + } + } else if (file_name == NULL) { + file_name = args->argv[i]; + } else { + log_error("command does not take 2 arguments"); + return KNOT_EINVAL; + } } - ret = conf_export(conf(), file_name, YP_SNONE); + if (file_name != NULL) { + if (export_schema) { + log_debug("exporting JSON schema into file '%s'", file_name); + } else { + log_debug("exporting confdb into file '%s'", file_name); + } + } + if (export_schema) { + ret = conf_export_schema(conf(), file_name); + } else { + ret = conf_export(conf(), file_name, YP_SNONE); + } if (ret == KNOT_EOK) { - if (args->argc > 0) { + if (file_name != NULL) { log_info("OK"); } } else { @@ -1345,7 +1369,7 @@ static const cmd_help_t cmd_help_table[] = { { CMD_CONF_INIT, "", "Initialize the confdb. (*)" }, { CMD_CONF_CHECK, "", "Check the server configuration. (*)" }, { CMD_CONF_IMPORT, " <filename> [+nopurge]", "Import a config file into the confdb. (*)" }, - { CMD_CONF_EXPORT, "[<filename>]", "Export the confdb into a config file or stdout. (*)" }, + { CMD_CONF_EXPORT, "[<filename>] [+schema]", "Export the confdb (or JSON schema) into a file or stdout. (*)" }, { CMD_CONF_LIST, "[<item>...]", "List the confdb sections or section items." }, { CMD_CONF_READ, "[<item>...]", "Get the item from the active confdb." }, { CMD_CONF_BEGIN, "", "Begin a writing confdb transaction." }, diff --git a/src/utils/knotd/main.c b/src/utils/knotd/main.c index 2355d9e..d4ebd53 100644 --- a/src/utils/knotd/main.c +++ b/src/utils/knotd/main.c @@ -273,7 +273,8 @@ static void event_loop(server_t *server, const char *socket, bool daemonize, log_info("control, binding to '%s'", listen); /* Bind the control socket. */ - int ret = knot_ctl_bind(ctl, listen); + uint16_t backlog = conf_get_int(conf(), C_CTL, C_BACKLOG); + int ret = knot_ctl_bind2(ctl, listen, backlog); if (ret != KNOT_EOK) { knot_ctl_free(ctl); log_fatal("control, failed to bind socket '%s' (%s)", diff --git a/src/utils/kxdpgun/main.c b/src/utils/kxdpgun/main.c index c9db312..8f4d402 100644 --- a/src/utils/kxdpgun/main.c +++ b/src/utils/kxdpgun/main.c @@ -30,6 +30,7 @@ #include <string.h> #include <time.h> #include <unistd.h> +#include <netdb.h> #include <arpa/inet.h> #include <netinet/in.h> @@ -205,12 +206,12 @@ static void print_stats(kxdpgun_stats_t *st, bool tcp, bool quic, bool recv, uin { pthread_mutex_lock(&st->mutex); -#define ps(counter) ((counter) * 1000 / (st->duration / 1000)) +#define ps(counter) ((typeof(counter))((counter) * 1000 / ((float)st->duration / 1000))) #define pct(counter) ((counter) * 100.0 / st->qry_sent) const char *name = tcp ? "SYNs: " : quic ? "initials:" : "queries: "; - printf("total %s %"PRIu64" (%"PRIu64" pps) (%f%%)\n", name, - st->qry_sent, ps(st->qry_sent), 100.0 * st->qry_sent / (st->duration / 1000000.0 * qps)); + printf("total %s %"PRIu64" (%"PRIu64" pps) (%f%%)\n", name, st->qry_sent, + ps(st->qry_sent), 100.0 * st->qry_sent / (st->duration / 1000000.0 * qps)); if (st->qry_sent > 0 && recv) { if (tcp || quic) { name = tcp ? "established:" : "handshakes: "; @@ -534,8 +535,8 @@ void *xdp_gun_thread(void *_ctx) } if (ctx->thread_id == 0) { - INFO2("using interface %s, XDP threads %u, %s%s%s, %s mode", - ctx->dev, ctx->n_threads, + INFO2("using interface %s, XDP threads %u, IPv%c/%s%s%s, %s mode", + ctx->dev, ctx->n_threads, (ctx->ipv6 ? '6' : '4'), (ctx->tcp ? "TCP" : ctx->quic ? "QUIC" : "UDP"), (ctx->sending_mode[0] != '\0' ? " mode " : ""), (ctx->sending_mode[0] != '\0' ? ctx->sending_mode : ""), @@ -989,6 +990,41 @@ static int mac_sscan(const char *src, uint8_t *dst) return KNOT_EOK; } +static bool resolve_name(char *target_str, xdp_gun_ctx_t *ctx) +{ + struct addrinfo *res = NULL, hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = 0, // any socket type + .ai_protocol = 0, // any protocol + }; + + int err = 0; + if ((err = getaddrinfo(target_str, NULL, &hints, &res)) != 0) { + ERR2("failed to resolve '%s' (%s)", target_str, gai_strerror(err)); + goto cleanup; + } + + for (struct addrinfo *i = res; i != NULL; i = i->ai_next) { + switch (i->ai_family) { + case AF_INET: + case AF_INET6: + ctx->ipv6 = (i->ai_family == AF_INET6); + assert(sizeof(ctx->target_ip_ss) >= i->ai_addrlen); + memcpy(&ctx->target_ip_ss, i->ai_addr, i->ai_addrlen); + goto cleanup; + default: + break; + }; + } + err = 1; + +cleanup: + if (res != NULL) { + freeaddrinfo(res); + } + return (err == 0); +} + static bool configure_target(char *target_str, char *local_ip, xdp_gun_ctx_t *ctx) { int val; @@ -998,16 +1034,8 @@ static bool configure_target(char *target_str, char *local_ip, xdp_gun_ctx_t *ct *at = '\0'; } - ctx->ipv6 = false; - if (inet_pton(AF_INET, target_str, &ctx->target_ip4.sin_addr) <= 0) { - ctx->ipv6 = true; - ctx->target_ip.sin6_family = AF_INET6; - if (inet_pton(AF_INET6, target_str, &ctx->target_ip.sin6_addr) <= 0) { - ERR2("invalid target IP"); - return false; - } - } else { - ctx->target_ip.sin6_family = AF_INET; + if (!resolve_name(target_str, ctx)) { + return false; } struct sockaddr_storage via = { 0 }; diff --git a/tests/libknot/test_xdp_tcp.c b/tests/libknot/test_xdp_tcp.c index 3e366b1..f6b11b0 100644 --- a/tests/libknot/test_xdp_tcp.c +++ b/tests/libknot/test_xdp_tcp.c @@ -92,7 +92,6 @@ static int mock_send(_unused_ knot_xdp_socket_t *sock, const knot_xdp_msg_t msgs ok(msg->payload.iov_len == 0, "send: is empty payload"); if (msg->flags & KNOT_XDP_MSG_RST) { - ok(!(msg->flags & KNOT_XDP_MSG_ACK), "send: no RST+ACK"); sent_rsts++; } else if (msg->flags & KNOT_XDP_MSG_SYN) { ok(msg->flags & KNOT_XDP_MSG_ACK, "send: is SYN+ACK"); diff --git a/tests/libknot/test_yparser.c b/tests/libknot/test_yparser.c index 8655096..8b6c31f 100644 --- a/tests/libknot/test_yparser.c +++ b/tests/libknot/test_yparser.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,6 +27,9 @@ const char *syntax_ok = " # comment\n" "a:\n" "a :\n" + "a: \"\"\n" + "a: []\n" + "a: [ ]\n" "a : #comment\n" "\n" "b: \"b\"\n" @@ -118,7 +121,7 @@ static void test_syntax_ok(yp_parser_t *yp) is_int(KNOT_EOK, ret, "set input string"); size_t line = 3; - for (int i = 0; i < 3; i++) { + for (int i = 0; i < 6; i++) { ret = yp_parse(yp); is_int(KNOT_EOK, ret, "parse %i. key0", i); ok(yp->key_len == 1 && yp->key[0] == 'a' && @@ -126,7 +129,7 @@ static void test_syntax_ok(yp_parser_t *yp) yp->line_count == line + i, "compare %i. key0", i); } - line += 4; + line += 7; for (int i = 0; i < 6; i++) { ret = yp_parse(yp); is_int(KNOT_EOK, ret, "parse %i. key0 with value", i); |