diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-14 16:17:58 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-14 16:17:58 +0000 |
commit | a04a7c41c9327144cc11ffd030c0efc2a4f85534 (patch) | |
tree | 812fe9d19c0c90324f80b838b1b1e2976a416999 /src | |
parent | Adding upstream version 3.3.5. (diff) | |
download | knot-a04a7c41c9327144cc11ffd030c0efc2a4f85534.tar.xz knot-a04a7c41c9327144cc11ffd030c0efc2a4f85534.zip |
Adding upstream version 3.3.6.upstream/3.3.6
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src')
78 files changed, 2452 insertions, 1610 deletions
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 }; |