lsquic_trans_params.c revision feca77f5
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_trans_params.c 4 */ 5 6#include <assert.h> 7#include <errno.h> 8#include <inttypes.h> 9#include <limits.h> 10#include <stddef.h> 11#include <stdint.h> 12#include <string.h> 13 14#include <arpa/inet.h> 15#include <sys/socket.h> 16 17#include "lsquic_byteswap.h" 18#include "lsquic_int_types.h" 19#include "lsquic_types.h" 20#include "lsquic_version.h" 21#include "lsquic_sizes.h" 22#include "lsquic_trans_params.h" 23#include "lsquic_util.h" 24#include "lsquic_varint.h" 25 26#define LSQUIC_LOGGER_MODULE LSQLM_TRAPA 27#include "lsquic_logger.h" 28 29 30static enum transport_param_id 31tpi_val_2_enum (uint64_t tpi_val) 32{ 33 switch (tpi_val) 34 { 35 case 0: return TPI_ORIGINAL_CONNECTION_ID; 36 case 1: return TPI_MAX_IDLE_TIMEOUT; 37 case 2: return TPI_STATELESS_RESET_TOKEN; 38 case 3: return TPI_MAX_PACKET_SIZE; 39 case 4: return TPI_INIT_MAX_DATA; 40 case 5: return TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL; 41 case 6: return TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE; 42 case 7: return TPI_INIT_MAX_STREAM_DATA_UNI; 43 case 8: return TPI_INIT_MAX_STREAMS_BIDI; 44 case 9: return TPI_INIT_MAX_STREAMS_UNI; 45 case 10: return TPI_ACK_DELAY_EXPONENT; 46 case 11: return TPI_MAX_ACK_DELAY; 47 case 12: return TPI_DISABLE_ACTIVE_MIGRATION; 48 case 13: return TPI_PREFERRED_ADDRESS; 49 case 14: return TPI_ACTIVE_CONNECTION_ID_LIMIT; 50#if LSQUIC_TEST_QUANTUM_READINESS 51 case 0xC37: return TPI_QUANTUM_READINESS; 52#endif 53 case 0x1057: return TPI_LOSS_BITS; 54 case 0xDE1A: return TPI_MIN_ACK_DELAY; 55 default: return INT_MAX; 56 } 57} 58 59 60static const unsigned short enum_2_tpi_val[LAST_TPI + 1] = 61{ 62 [TPI_ORIGINAL_CONNECTION_ID] = 0x0, 63 [TPI_MAX_IDLE_TIMEOUT] = 0x1, 64 [TPI_STATELESS_RESET_TOKEN] = 0x2, 65 [TPI_MAX_PACKET_SIZE] = 0x3, 66 [TPI_INIT_MAX_DATA] = 0x4, 67 [TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL] = 0x5, 68 [TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE] = 0x6, 69 [TPI_INIT_MAX_STREAM_DATA_UNI] = 0x7, 70 [TPI_INIT_MAX_STREAMS_BIDI] = 0x8, 71 [TPI_INIT_MAX_STREAMS_UNI] = 0x9, 72 [TPI_ACK_DELAY_EXPONENT] = 0xA, 73 [TPI_MAX_ACK_DELAY] = 0xB, 74 [TPI_DISABLE_ACTIVE_MIGRATION] = 0xC, 75 [TPI_PREFERRED_ADDRESS] = 0xD, 76 [TPI_ACTIVE_CONNECTION_ID_LIMIT] = 0xE, 77#if LSQUIC_TEST_QUANTUM_READINESS 78 [TPI_QUANTUM_READINESS] = 0xC37, 79#endif 80 [TPI_LOSS_BITS] = 0x1057, 81 [TPI_MIN_ACK_DELAY] = 0xDE1A, 82}; 83 84 85static const char * const tpi2str[LAST_TPI + 1] = 86{ 87 [TPI_ORIGINAL_CONNECTION_ID] = "original_connection_id", 88 [TPI_MAX_IDLE_TIMEOUT] = "max_idle_timeout", 89 [TPI_STATELESS_RESET_TOKEN] = "stateless_reset_token", 90 [TPI_MAX_PACKET_SIZE] = "max_packet_size", 91 [TPI_INIT_MAX_DATA] = "init_max_data", 92 [TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL] = "init_max_stream_data_bidi_local", 93 [TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE] = "init_max_stream_data_bidi_remote", 94 [TPI_INIT_MAX_STREAM_DATA_UNI] = "init_max_stream_data_uni", 95 [TPI_INIT_MAX_STREAMS_BIDI] = "init_max_streams_bidi", 96 [TPI_INIT_MAX_STREAMS_UNI] = "init_max_streams_uni", 97 [TPI_ACK_DELAY_EXPONENT] = "ack_delay_exponent", 98 [TPI_MAX_ACK_DELAY] = "max_ack_delay", 99 [TPI_DISABLE_ACTIVE_MIGRATION] = "disable_active_migration", 100 [TPI_PREFERRED_ADDRESS] = "preferred_address", 101 [TPI_ACTIVE_CONNECTION_ID_LIMIT] = "active_connection_id_limit", 102#if LSQUIC_TEST_QUANTUM_READINESS 103 [TPI_QUANTUM_READINESS] = "quantum_readiness", 104#endif 105 [TPI_LOSS_BITS] = "loss_bits", 106 [TPI_MIN_ACK_DELAY] = "min_ack_delay", 107}; 108 109 110static const uint64_t def_vals[MAX_NUM_WITH_DEF_TPI + 1] = 111{ 112 [TPI_MAX_PACKET_SIZE] = TP_DEF_MAX_PACKET_SIZE, 113 [TPI_ACK_DELAY_EXPONENT] = TP_DEF_ACK_DELAY_EXP, 114 [TPI_INIT_MAX_STREAMS_UNI] = TP_DEF_INIT_MAX_STREAMS_UNI, 115 [TPI_INIT_MAX_STREAMS_BIDI] = TP_DEF_INIT_MAX_STREAMS_BIDI, 116 [TPI_INIT_MAX_DATA] = TP_DEF_INIT_MAX_DATA, 117 [TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL] = TP_DEF_INIT_MAX_STREAM_DATA_BIDI_LOCAL, 118 [TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE] = TP_DEF_INIT_MAX_STREAM_DATA_BIDI_REMOTE, 119 [TPI_INIT_MAX_STREAM_DATA_UNI] = TP_DEF_INIT_MAX_STREAM_DATA_UNI, 120 [TPI_MAX_IDLE_TIMEOUT] = TP_DEF_MAX_IDLE_TIMEOUT, 121 [TPI_MAX_ACK_DELAY] = TP_DEF_MAX_ACK_DELAY, 122 [TPI_ACTIVE_CONNECTION_ID_LIMIT] = TP_DEF_ACTIVE_CONNECTION_ID_LIMIT, 123}; 124 125 126static const uint64_t max_vals[MAX_NUMERIC_TPI + 1] = 127{ 128 [TPI_MAX_PACKET_SIZE] = VINT_MAX_VALUE, 129 [TPI_ACK_DELAY_EXPONENT] = VINT_MAX_VALUE, 130 [TPI_INIT_MAX_STREAMS_UNI] = VINT_MAX_VALUE, 131 [TPI_INIT_MAX_STREAMS_BIDI] = VINT_MAX_VALUE, 132 [TPI_INIT_MAX_DATA] = VINT_MAX_VALUE, 133 [TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL] = VINT_MAX_VALUE, 134 [TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE] = VINT_MAX_VALUE, 135 [TPI_INIT_MAX_STREAM_DATA_UNI] = VINT_MAX_VALUE, 136 [TPI_MAX_IDLE_TIMEOUT] = VINT_MAX_VALUE, 137 [TPI_MAX_ACK_DELAY] = TP_MAX_MAX_ACK_DELAY, 138 [TPI_ACTIVE_CONNECTION_ID_LIMIT] = VINT_MAX_VALUE, 139 [TPI_LOSS_BITS] = 1, 140 [TPI_MIN_ACK_DELAY] = (1u << 24) - 1u, 141}; 142 143 144static const uint64_t min_vals[MAX_NUMERIC_TPI + 1] = 145{ 146 [TPI_MIN_ACK_DELAY] = 1, 147}; 148 149 150static size_t 151preferred_address_size (const struct transport_params *params) 152{ 153 return sizeof(params->tp_preferred_address.ipv4_addr) 154 + sizeof(params->tp_preferred_address.ipv4_port) 155 + sizeof(params->tp_preferred_address.ipv6_addr) 156 + sizeof(params->tp_preferred_address.ipv6_port) 157 + 1 + params->tp_preferred_address.cid.len 158 + sizeof(params->tp_preferred_address.srst) 159 ; 160} 161 162 163int 164lsquic_tp_has_pref_ipv4 (const struct transport_params *params) 165{ 166 return (params->tp_set & (1 << TPI_PREFERRED_ADDRESS)) 167 && params->tp_preferred_address.ipv4_port 168 && !lsquic_is_zero(params->tp_preferred_address.ipv4_addr, 169 sizeof(params->tp_preferred_address.ipv4_addr)); 170} 171 172 173int 174lsquic_tp_has_pref_ipv6 (const struct transport_params *params) 175{ 176 return (params->tp_set & (1 << TPI_PREFERRED_ADDRESS)) 177 && params->tp_preferred_address.ipv6_port 178 && !lsquic_is_zero(params->tp_preferred_address.ipv6_addr, 179 sizeof(params->tp_preferred_address.ipv6_addr)); 180} 181 182 183int 184lsquic_tp_encode (const struct transport_params *params, int is_server, 185 unsigned char *const buf, size_t bufsz) 186{ 187 unsigned char *p; 188 size_t need = 2; 189 uint16_t u16; 190 enum transport_param_id tpi; 191 unsigned set; 192 unsigned bits[MAX_NUMERIC_TPI + 1]; 193 194 set = params->tp_set; /* Will turn bits off for default values */ 195 196 if (is_server) 197 { 198 if (set & (1 << TPI_ORIGINAL_CONNECTION_ID)) 199 need += 4 + params->tp_original_cid.len; 200 if (set & (1 << TPI_STATELESS_RESET_TOKEN)) 201 need += 4 + sizeof(params->tp_stateless_reset_token); 202 if (set & (1 << TPI_PREFERRED_ADDRESS)) 203 need += 4 + preferred_address_size(params); 204 } 205#if LSQUIC_TEST_QUANTUM_READINESS 206 else if (set & (1 << TPI_QUANTUM_READINESS)) 207 need += 4 + QUANTUM_READY_SZ; 208#endif 209 210 for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi) 211 if (set & (1 << tpi)) 212 { 213 if (tpi > MAX_NUM_WITH_DEF_TPI 214 || params->tp_numerics[tpi] != def_vals[tpi]) 215 { 216 if (params->tp_numerics[tpi] >= min_vals[tpi] 217 && params->tp_numerics[tpi] <= max_vals[tpi]) 218 { 219 bits[tpi] = vint_val2bits(params->tp_numerics[tpi]); 220 need += 4 + (1 << bits[tpi]); 221 } 222 else if (params->tp_numerics[tpi] > max_vals[tpi]) 223 { 224 LSQ_DEBUG("numeric value of %s is too large (%"PRIu64" vs " 225 "maximum of %"PRIu64")", tpi2str[tpi], 226 params->tp_numerics[tpi], max_vals[tpi]); 227 return -1; 228 } 229 else 230 { 231 LSQ_DEBUG("numeric value of %s is too small (%"PRIu64" vs " 232 "minimum " "of %"PRIu64")", 233 tpi2str[tpi], params->tp_numerics[tpi], min_vals[tpi]); 234 return -1; 235 } 236 } 237 else 238 set &= ~(1 << tpi); /* Don't write default value */ 239 } 240 241 for (; tpi <= MAX_EMPTY_TPI; ++tpi) 242 if (set & (1 << tpi)) 243 need += 4 + 0; 244 245 if (need > bufsz || need > UINT16_MAX) 246 { 247 errno = ENOBUFS; 248 return -1; 249 } 250 251 p = buf; 252 253#define WRITE_TO_P(src, len) do { \ 254 memcpy(p, src, len); \ 255 p += len; \ 256} while (0) 257 258#if __BYTE_ORDER == __LITTLE_ENDIAN 259#define WRITE_UINT_TO_P(val, width) do { \ 260 u##width = bswap_##width(val); \ 261 WRITE_TO_P(&u##width, sizeof(u##width)); \ 262} while (0) 263#else 264#define WRITE_UINT_TO_P(val, width) do { \ 265 u##width = val; \ 266 WRITE_TO_P(&u##width, sizeof(u##width)); \ 267} while (0) 268#endif 269 270#define WRITE_PARAM_TO_P(tpidx, tpval, width) do { \ 271 WRITE_UINT_TO_P(tpidx, 16); \ 272 WRITE_UINT_TO_P(width / 8, 16); \ 273 if (width > 8) \ 274 WRITE_UINT_TO_P(tpval, width); \ 275 else if (width) \ 276 *p++ = tpval; \ 277} while (0) 278 279 WRITE_UINT_TO_P(need - 2 + buf - p, 16); 280 281 for (tpi = 0; tpi <= LAST_TPI; ++tpi) 282 if (set & (1 << tpi)) 283 { 284 WRITE_UINT_TO_P(enum_2_tpi_val[tpi], 16); 285 switch (tpi) 286 { 287 case TPI_MAX_IDLE_TIMEOUT: 288 case TPI_MAX_PACKET_SIZE: 289 case TPI_INIT_MAX_DATA: 290 case TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL: 291 case TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE: 292 case TPI_INIT_MAX_STREAM_DATA_UNI: 293 case TPI_INIT_MAX_STREAMS_BIDI: 294 case TPI_INIT_MAX_STREAMS_UNI: 295 case TPI_ACK_DELAY_EXPONENT: 296 case TPI_MAX_ACK_DELAY: 297 case TPI_ACTIVE_CONNECTION_ID_LIMIT: 298 case TPI_LOSS_BITS: 299 case TPI_MIN_ACK_DELAY: 300 WRITE_UINT_TO_P(1 << bits[tpi], 16); 301 vint_write(p, params->tp_numerics[tpi], bits[tpi], 302 1 << bits[tpi]); 303 p += 1 << bits[tpi]; 304 break; 305 case TPI_ORIGINAL_CONNECTION_ID: 306 WRITE_UINT_TO_P(params->tp_original_cid.len, 16); 307 WRITE_TO_P(params->tp_original_cid.idbuf, 308 params->tp_original_cid.len); 309 break; 310 case TPI_STATELESS_RESET_TOKEN: 311 WRITE_UINT_TO_P(sizeof(params->tp_stateless_reset_token), 16); 312 WRITE_TO_P(params->tp_stateless_reset_token, 313 sizeof(params->tp_stateless_reset_token)); 314 break; 315 case TPI_PREFERRED_ADDRESS: 316 WRITE_UINT_TO_P(preferred_address_size(params), 16); 317 WRITE_TO_P(¶ms->tp_preferred_address.ipv4_addr, 318 sizeof(params->tp_preferred_address.ipv4_addr)); 319 WRITE_UINT_TO_P(params->tp_preferred_address.ipv4_port, 16); 320 WRITE_TO_P(¶ms->tp_preferred_address.ipv6_addr, 321 sizeof(params->tp_preferred_address.ipv6_addr)); 322 WRITE_UINT_TO_P(params->tp_preferred_address.ipv6_port, 16); 323 *p++ = params->tp_preferred_address.cid.len; 324 WRITE_TO_P(params->tp_preferred_address.cid.idbuf, 325 params->tp_preferred_address.cid.len); 326 WRITE_TO_P(params->tp_preferred_address.srst, 327 sizeof(params->tp_preferred_address.srst)); 328 break; 329 case TPI_DISABLE_ACTIVE_MIGRATION: 330 WRITE_UINT_TO_P(0, 16); 331 break; 332#if LSQUIC_TEST_QUANTUM_READINESS 333 case TPI_QUANTUM_READINESS: 334 WRITE_UINT_TO_P(QUANTUM_READY_SZ, 16); 335 memset(p, 'Q', QUANTUM_READY_SZ); 336 p += QUANTUM_READY_SZ; 337 break; 338#endif 339 } 340 } 341 342 assert(buf + need == p); 343 return (int) (p - buf); 344 345#undef WRITE_TO_P 346#undef WRITE_UINT_TO_P 347} 348 349 350int 351lsquic_tp_decode (const unsigned char *const buf, size_t bufsz, 352 int is_server, 353 struct transport_params *params) 354{ 355 const unsigned char *p, *end, *q; 356 uint16_t len, param_id, tlen; 357 enum transport_param_id tpi; 358 unsigned set_of_ids; 359 int s; 360 361 p = buf; 362 end = buf + bufsz; 363 364 *params = TP_INITIALIZER(); 365 366 if (end - p < 2) 367 return -1; 368 READ_UINT(len, 16, p, 2); 369 p += 2; 370 if (len > end - p) 371 return -1; 372 end = p + len; 373 374#define EXPECT_LEN(expected_len) do { \ 375 if (expected_len != len) \ 376 return -1; \ 377} while (0) 378 379#define EXPECT_AT_LEAST(expected_len) do { \ 380 if ((expected_len) > (uintptr_t) (p + len - q)) \ 381 return -1; \ 382} while (0) 383 384 set_of_ids = 0; 385 while (p + 4 <= end) 386 { 387 READ_UINT(param_id, 16, p, 2); 388 p += 2; 389 READ_UINT(len, 16, p, 2); 390 p += 2; 391 if (len > end - p) 392 return -1; 393 tpi = tpi_val_2_enum(param_id); 394 if (tpi <= LAST_TPI) 395 { 396 if (set_of_ids & (1 << tpi)) 397 return -1; 398 set_of_ids |= 1 << tpi; 399 } 400 switch (tpi) 401 { 402 case TPI_MAX_IDLE_TIMEOUT: 403 case TPI_MAX_PACKET_SIZE: 404 case TPI_INIT_MAX_DATA: 405 case TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL: 406 case TPI_INIT_MAX_STREAM_DATA_BIDI_REMOTE: 407 case TPI_INIT_MAX_STREAM_DATA_UNI: 408 case TPI_INIT_MAX_STREAMS_BIDI: 409 case TPI_INIT_MAX_STREAMS_UNI: 410 case TPI_ACK_DELAY_EXPONENT: 411 case TPI_MAX_ACK_DELAY: 412 case TPI_ACTIVE_CONNECTION_ID_LIMIT: 413 case TPI_LOSS_BITS: 414 case TPI_MIN_ACK_DELAY: 415 switch (len) 416 { 417 case 1: 418 case 2: 419 case 4: 420 case 8: 421 s = vint_read(p, p + len, ¶ms->tp_numerics[tpi]); 422 if (s == len) 423 { 424 if (params->tp_numerics[tpi] > max_vals[tpi]) 425 { 426 LSQ_DEBUG("numeric value of %s is too large " 427 "(%"PRIu64" vs maximum of %"PRIu64, tpi2str[tpi], 428 params->tp_numerics[tpi], max_vals[tpi]); 429 return -1; 430 } 431 else if (params->tp_numerics[tpi] < min_vals[tpi]) 432 { 433 LSQ_DEBUG("numeric value of %s is too small " 434 "(%"PRIu64" vs minimum of %"PRIu64, tpi2str[tpi], 435 params->tp_numerics[tpi], min_vals[tpi]); 436 return -1; 437 } 438 break; 439 } 440 else 441 { 442 LSQ_DEBUG("cannot read the value of numeric transport " 443 "param %u of length %u", param_id, len); 444 return -1; 445 } 446 default: 447 LSQ_DEBUG("invalid length=%u for numeric transport " 448 "parameter 0x%X", len, param_id); 449 return -1; 450 } 451 break; 452 case TPI_DISABLE_ACTIVE_MIGRATION: 453 EXPECT_LEN(0); 454 break; 455 case TPI_STATELESS_RESET_TOKEN: 456 /* Client MUST not include reset token, 457 * see [draft-ietf-quic-transport-11], Section 6.4.1 458 */ 459 if (!is_server) 460 return -1; 461 EXPECT_LEN(sizeof(params->tp_stateless_reset_token)); 462 memcpy(params->tp_stateless_reset_token, p, 463 sizeof(params->tp_stateless_reset_token)); 464 break; 465 case TPI_ORIGINAL_CONNECTION_ID: 466 /* Client MUST not original connecti ID, 467 * see [draft-ietf-quic-transport-15], Section 6.6.1 468 */ 469 if (!is_server) 470 return -1; 471 if (len > MAX_CID_LEN) 472 return -1; 473 memcpy(params->tp_original_cid.idbuf, p, len); 474 params->tp_original_cid.len = len; 475 break; 476 case TPI_PREFERRED_ADDRESS: 477 /* Client MUST not include preferred address, 478 * see [draft-ietf-quic-transport-12], Section 6.4.1 479 */ 480 if (!is_server) 481 return -1; 482 q = p; 483 EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv4_addr)); 484 memcpy(params->tp_preferred_address.ipv4_addr, q, 485 sizeof(params->tp_preferred_address.ipv4_addr)); 486 q += sizeof(params->tp_preferred_address.ipv4_addr); 487 EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv4_port)); 488 READ_UINT(params->tp_preferred_address.ipv4_port, 16, q, 2); 489 q += 2; 490 EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv6_addr)); 491 memcpy(params->tp_preferred_address.ipv6_addr, q, 492 sizeof(params->tp_preferred_address.ipv6_addr)); 493 q += sizeof(params->tp_preferred_address.ipv6_addr); 494 EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.ipv6_port)); 495 READ_UINT(params->tp_preferred_address.ipv6_port, 16, q, 2); 496 q += 2; 497 EXPECT_AT_LEAST(1); 498 tlen = *q; 499 q += 1; 500 if (tlen < 4 || tlen > MAX_CID_LEN) 501 { 502 LSQ_DEBUG("preferred server address contains invalid " 503 "CID length of %"PRIu16" bytes", tlen); 504 return -1; 505 } 506 EXPECT_AT_LEAST(tlen); 507 memcpy(params->tp_preferred_address.cid.idbuf, q, tlen); 508 params->tp_preferred_address.cid.len = tlen; 509 q += tlen; 510 EXPECT_AT_LEAST(sizeof(params->tp_preferred_address.srst)); 511 memcpy(params->tp_preferred_address.srst, q, 512 sizeof(params->tp_preferred_address.srst)); 513 q += sizeof(params->tp_preferred_address.srst); 514 if (q != p + len) 515 return -1; 516 break; 517 default: 518 /* Do nothing: skip this transport parameter */ 519 break; 520 } 521 p += len; 522 if (tpi <= LAST_TPI) 523 { 524 params->tp_set |= 1 << tpi; 525 params->tp_decoded |= 1 << tpi; 526 } 527 } 528 529 if (p != end) 530 return -1; 531 532 if ((params->tp_set & (1 << TPI_MIN_ACK_DELAY)) 533 && params->tp_numerics[TPI_MIN_ACK_DELAY] 534 > params->tp_numerics[TPI_MAX_ACK_DELAY] * 1000) 535 { 536 LSQ_DEBUG("min_ack_delay (%"PRIu64" usec) is larger than " 537 "max_ack_delay (%"PRIu64" ms)", 538 params->tp_numerics[TPI_MIN_ACK_DELAY], 539 params->tp_numerics[TPI_MAX_ACK_DELAY]); 540 return -1; 541 } 542 543 return (int) (end - buf); 544#undef EXPECT_LEN 545} 546 547 548void 549lsquic_tp_to_str (const struct transport_params *params, char *buf, size_t sz) 550{ 551 char *const end = buf + sz; 552 int nw; 553 enum transport_param_id tpi; 554 char tok_str[sizeof(params->tp_stateless_reset_token) * 2 + 1]; 555 char addr_str[INET6_ADDRSTRLEN]; 556 557 for (tpi = 0; tpi <= MAX_NUMERIC_TPI; ++tpi) 558 if (params->tp_set & (1 << tpi)) 559 { 560 nw = snprintf(buf, end - buf, "%.*s%s: %"PRIu64, 561 (buf + sz > end) << 1, "; ", tpi2str[tpi], 562 params->tp_numerics[tpi]); 563 buf += nw; 564 if (buf >= end) 565 return; 566 } 567 for (; tpi <= MAX_EMPTY_TPI; ++tpi) 568 if (params->tp_set & (1 << TPI_INIT_MAX_STREAM_DATA_BIDI_LOCAL)) 569 { 570 nw = snprintf(buf, end - buf, "%.*s%s", 571 (buf + sz > end) << 1, "; ", tpi2str[tpi]); 572 buf += nw; 573 if (buf >= end) 574 return; 575 } 576#if LSQUIC_TEST_QUANTUM_READINESS 577 if (params->tp_set & (1 << TPI_QUANTUM_READINESS)) 578 { 579 nw = snprintf(buf, end - buf, "%.*s%s", 580 (buf + sz > end) << 1, "; ", tpi2str[TPI_QUANTUM_READINESS]); 581 buf += nw; 582 if (buf >= end) 583 return; 584 } 585#endif 586 if (params->tp_set & (1 << TPI_STATELESS_RESET_TOKEN)) 587 { 588 lsquic_hexstr(params->tp_stateless_reset_token, 589 sizeof(params->tp_stateless_reset_token), tok_str, sizeof(tok_str)); 590 nw = snprintf(buf, end - buf, "; stateless_reset_token: %s", tok_str); 591 buf += nw; 592 if (buf >= end) 593 return; 594 } 595 if (params->tp_set & (1 << TPI_ORIGINAL_CONNECTION_ID)) 596 { 597 char cidbuf_[MAX_CID_LEN * 2 + 1]; 598 nw = snprintf(buf, end - buf, "; original DCID (ODCID): %"CID_FMT, 599 CID_BITS(¶ms->tp_original_cid)); 600 buf += nw; 601 if (buf >= end) 602 return; 603 } 604 if (lsquic_tp_has_pref_ipv4(params)) 605 { 606 if (inet_ntop(AF_INET, params->tp_preferred_address.ipv4_addr, 607 addr_str, sizeof(addr_str))) 608 { 609 nw = snprintf(buf, end - buf, "; IPv4 preferred address: %s:%u", 610 addr_str, params->tp_preferred_address.ipv4_port); 611 buf += nw; 612 if (buf >= end) 613 return; 614 } 615 } 616 if (lsquic_tp_has_pref_ipv6(params)) 617 { 618 if (inet_ntop(AF_INET6, params->tp_preferred_address.ipv6_addr, 619 addr_str, sizeof(addr_str))) 620 { 621 nw = snprintf(buf, end - buf, "; IPv6 preferred address: %s:%u", 622 addr_str, params->tp_preferred_address.ipv6_port); 623 buf += nw; 624 if (buf >= end) 625 return; 626 } 627 } 628} 629