lsquic_parse_iquic_common.c revision 9fc12041
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * Parsing routines shared by all IETF QUIC versions. 4 */ 5 6#include <assert.h> 7#include <stddef.h> 8#include <stdint.h> 9#include <string.h> 10#include <sys/queue.h> 11#include <sys/types.h> 12 13#include <openssl/rand.h> 14 15#include "lsquic_types.h" 16#include "lsquic_int_types.h" 17#include "lsquic_packet_common.h" 18#include "lsquic_packet_in.h" 19#include "lsquic_parse_common.h" 20#include "lsquic_parse.h" 21#include "lsquic_version.h" 22#include "lsquic.h" 23#include "lsquic_logger.h" 24#include "lsquic_byteswap.h" 25#include "lsquic_varint.h" 26#include "lsquic_enc_sess.h" 27#include "lsquic_tokgen.h" 28#include "lsquic.h" 29#include "lsquic_mm.h" 30#include "lsquic_engine_public.h" 31#include "lsquic_ietf.h" 32 33 34/* [draft-ietf-quic-transport-17] Section-17.2 */ 35static const enum header_type bits2ht[4] = 36{ 37 [0] = HETY_INITIAL, 38 [1] = HETY_0RTT, 39 [2] = HETY_HANDSHAKE, 40 [3] = HETY_RETRY, 41}; 42 43 44int 45lsquic_Q046_parse_packet_in_long_begin (struct lsquic_packet_in *packet_in, 46 size_t length, int is_server, unsigned cid_len, 47 struct packin_parse_state *state) 48{ 49 const unsigned char *p = packet_in->pi_data; 50 const unsigned char *const end = p + length; 51 lsquic_ver_tag_t tag; 52 enum header_type header_type; 53 unsigned dcil, scil, packet_len; 54 int verneg; 55 unsigned char first_byte; 56 lsquic_packno_t packno; 57 58 if (length < 6) 59 return -1; 60 first_byte = *p++; 61 62 memcpy(&tag, p, 4); 63 p += 4; 64 verneg = 0 == tag; 65 if (!verneg) 66 header_type = bits2ht[ (first_byte >> 4) & 3 ]; 67 else 68 header_type = HETY_VERNEG; 69 70 packet_in->pi_header_type = header_type; 71 72 dcil = p[0] >> 4; 73 if (dcil) 74 dcil += 3; 75 scil = p[0] & 0xF; 76 if (scil) 77 scil += 3; 78 ++p; 79 80 /* Chromium comments state that the client sends packets with destination 81 * CID of 8 bytes and source CID of 0 bytes and the server does it the 82 * other way around. 83 */ 84 if (is_server) 85 { 86 if (!(dcil == cid_len && scil == 0)) 87 return -1; 88 } 89 else 90 if (!(dcil == 0 && scil == cid_len)) 91 return -1; 92 93 if (!verneg) 94 { 95 packet_in->pi_flags |= (first_byte & 3) << PIBIT_BITS_SHIFT; 96 packet_len = 1 + (first_byte & 3); 97 if (end - p < (ptrdiff_t) (dcil + scil + packet_len)) 98 return -1; 99 } 100 else 101 { 102 /* Need at least one version in the version array: add 4 */ 103 if (end - p < (ptrdiff_t) (dcil + scil + 4)) 104 return -1; 105#ifdef WIN32 106 /* Useless initialization: */ 107 packet_len = 0; 108#endif 109 } 110 111 memcpy(&packet_in->pi_dcid.idbuf, p, cid_len); 112 packet_in->pi_dcid.len = cid_len; 113 p += cid_len; 114 packet_in->pi_flags |= PI_CONN_ID; 115 116 if (!verneg) 117 { 118 READ_UINT(packno, 64, p, packet_len); 119 packet_in->pi_packno = packno; 120 p += packet_len; 121 packet_in->pi_quic_ver = 1; 122 if (is_server || HETY_0RTT != header_type) 123 packet_in->pi_nonce = 0; 124 else 125 { 126 packet_in->pi_nonce = p - packet_in->pi_data; 127 p += 32; 128 } 129 } 130 else 131 { 132 if (p >= end || (3 & (uintptr_t) (end - p))) 133 return -1; 134 packet_in->pi_quic_ver = p - packet_in->pi_data; 135 p = end; 136 } 137 138 packet_in->pi_header_sz = p - packet_in->pi_data; 139 packet_in->pi_frame_types = 0; 140 packet_in->pi_data_sz = length; 141 packet_in->pi_refcnt = 0; 142 packet_in->pi_received = 0; 143 144 return 0; 145} 146 147 148int 149lsquic_Q046_parse_packet_in_short_begin (lsquic_packet_in_t *packet_in, 150 size_t length, int is_server, unsigned cid_len, 151 struct packin_parse_state *state) 152{ 153 const unsigned char *p = packet_in->pi_data; 154 const unsigned char *const pend = packet_in->pi_data + length; 155 unsigned packet_len, header_len; 156 lsquic_packno_t packno; 157 158 if (*p & 0x40) /* Q046 and higher */ 159 packet_len = 1 + (*p & 3); 160 else 161 return -1; 162 163 if (is_server) 164 header_len = 1 + cid_len + packet_len; 165 else 166 header_len = 1 + packet_len; 167 168 if (pend - p < (ptrdiff_t) header_len) 169 return -1; 170 171 packet_in->pi_flags |= (*p & 3) << PIBIT_BITS_SHIFT; 172 ++p; 173 if (is_server) 174 { 175 memcpy(packet_in->pi_dcid.idbuf, packet_in->pi_data + 1, cid_len); 176 packet_in->pi_dcid.len = cid_len; 177 packet_in->pi_flags |= PI_CONN_ID; 178 p += cid_len; 179 } 180 181 READ_UINT(packno, 64, p, packet_len); 182 packet_in->pi_packno = packno; 183 p += packet_len; 184 185 packet_in->pi_header_type = HETY_NOT_SET; 186 packet_in->pi_quic_ver = 0; 187 packet_in->pi_nonce = 0; 188 packet_in->pi_header_sz = p - packet_in->pi_data; 189 packet_in->pi_frame_types = 0; 190 packet_in->pi_data_sz = length; 191 packet_in->pi_refcnt = 0; 192 packet_in->pi_received = 0; 193 194 return 0; 195} 196 197 198/* This is a bare-bones version of lsquic_Q046_parse_packet_in_long_begin() 199 */ 200int 201lsquic_is_valid_iquic_hs_packet (const unsigned char *buf, size_t length, 202 lsquic_ver_tag_t *tagp) 203{ 204 const unsigned char *p = buf; 205 const unsigned char *const end = p + length; 206 lsquic_ver_tag_t tag; 207 unsigned dcil, scil, packet_len; 208 unsigned char first_byte; 209 const unsigned cid_len = 8; 210 211 if (length < 6) 212 return 0; 213 first_byte = *p++; 214 215 memcpy(&tag, p, 4); 216 p += 4; 217 if (0 == tag) 218 return 0; /* Client never sends version negotiation */ 219 220 dcil = p[0] >> 4; 221 if (dcil) 222 dcil += 3; 223 scil = p[0] & 0xF; 224 if (scil) 225 scil += 3; 226 ++p; 227 228 if (!(dcil == cid_len && scil == 0)) 229 return 0; 230 231 packet_len = first_byte & 3; 232 233 if (end - p >= (ptrdiff_t) (dcil + scil + packet_len)) 234 { 235 *tagp = tag; 236 return 1; 237 } 238 else 239 return 0; 240} 241 242 243const enum quic_frame_type lsquic_iquic_byte2type[0x100] = 244{ 245 [0x00] = QUIC_FRAME_PADDING, 246 [0x01] = QUIC_FRAME_PING, 247 [0x02] = QUIC_FRAME_ACK, 248 [0x03] = QUIC_FRAME_ACK, 249 [0x04] = QUIC_FRAME_RST_STREAM, 250 [0x05] = QUIC_FRAME_STOP_SENDING, 251 [0x06] = QUIC_FRAME_CRYPTO, 252 [0x07] = QUIC_FRAME_NEW_TOKEN, 253 [0x08] = QUIC_FRAME_STREAM, 254 [0x09] = QUIC_FRAME_STREAM, 255 [0x0A] = QUIC_FRAME_STREAM, 256 [0x0B] = QUIC_FRAME_STREAM, 257 [0x0C] = QUIC_FRAME_STREAM, 258 [0x0D] = QUIC_FRAME_STREAM, 259 [0x0E] = QUIC_FRAME_STREAM, 260 [0x0F] = QUIC_FRAME_STREAM, 261 [0x10] = QUIC_FRAME_MAX_DATA, 262 [0x11] = QUIC_FRAME_MAX_STREAM_DATA, 263 [0x12] = QUIC_FRAME_MAX_STREAMS, 264 [0x13] = QUIC_FRAME_MAX_STREAMS, 265 [0x14] = QUIC_FRAME_BLOCKED, 266 [0x15] = QUIC_FRAME_STREAM_BLOCKED, 267 [0x16] = QUIC_FRAME_STREAMS_BLOCKED, 268 [0x17] = QUIC_FRAME_STREAMS_BLOCKED, 269 [0x18] = QUIC_FRAME_NEW_CONNECTION_ID, 270 [0x19] = QUIC_FRAME_RETIRE_CONNECTION_ID, 271 [0x1A] = QUIC_FRAME_PATH_CHALLENGE, 272 [0x1B] = QUIC_FRAME_PATH_RESPONSE, 273 [0x1C] = QUIC_FRAME_CONNECTION_CLOSE, 274 [0x1D] = QUIC_FRAME_CONNECTION_CLOSE, 275 [0x1E] = QUIC_FRAME_HANDSHAKE_DONE, 276 [0x1F] = QUIC_FRAME_INVALID, 277 [0x20] = QUIC_FRAME_INVALID, 278 [0x21] = QUIC_FRAME_INVALID, 279 [0x22] = QUIC_FRAME_INVALID, 280 [0x23] = QUIC_FRAME_INVALID, 281 [0x24] = QUIC_FRAME_INVALID, 282 [0x25] = QUIC_FRAME_INVALID, 283 [0x26] = QUIC_FRAME_INVALID, 284 [0x27] = QUIC_FRAME_INVALID, 285 [0x28] = QUIC_FRAME_INVALID, 286 [0x29] = QUIC_FRAME_INVALID, 287 [0x2A] = QUIC_FRAME_INVALID, 288 [0x2B] = QUIC_FRAME_INVALID, 289 [0x2C] = QUIC_FRAME_INVALID, 290 [0x2D] = QUIC_FRAME_INVALID, 291 [0x2E] = QUIC_FRAME_INVALID, 292 [0x2F] = QUIC_FRAME_INVALID, 293 [0x30] = QUIC_FRAME_INVALID, 294 [0x31] = QUIC_FRAME_INVALID, 295 [0x32] = QUIC_FRAME_INVALID, 296 [0x33] = QUIC_FRAME_INVALID, 297 [0x34] = QUIC_FRAME_INVALID, 298 [0x35] = QUIC_FRAME_INVALID, 299 [0x36] = QUIC_FRAME_INVALID, 300 [0x37] = QUIC_FRAME_INVALID, 301 [0x38] = QUIC_FRAME_INVALID, 302 [0x39] = QUIC_FRAME_INVALID, 303 [0x3A] = QUIC_FRAME_INVALID, 304 [0x3B] = QUIC_FRAME_INVALID, 305 [0x3C] = QUIC_FRAME_INVALID, 306 [0x3D] = QUIC_FRAME_INVALID, 307 [0x3E] = QUIC_FRAME_INVALID, 308 [0x3F] = QUIC_FRAME_INVALID, 309 [0x40] = QUIC_FRAME_INVALID, 310 [0x41] = QUIC_FRAME_INVALID, 311 [0x42] = QUIC_FRAME_INVALID, 312 [0x43] = QUIC_FRAME_INVALID, 313 [0x44] = QUIC_FRAME_INVALID, 314 [0x45] = QUIC_FRAME_INVALID, 315 [0x46] = QUIC_FRAME_INVALID, 316 [0x47] = QUIC_FRAME_INVALID, 317 [0x48] = QUIC_FRAME_INVALID, 318 [0x49] = QUIC_FRAME_INVALID, 319 [0x4A] = QUIC_FRAME_INVALID, 320 [0x4B] = QUIC_FRAME_INVALID, 321 [0x4C] = QUIC_FRAME_INVALID, 322 [0x4D] = QUIC_FRAME_INVALID, 323 [0x4E] = QUIC_FRAME_INVALID, 324 [0x4F] = QUIC_FRAME_INVALID, 325 [0x50] = QUIC_FRAME_INVALID, 326 [0x51] = QUIC_FRAME_INVALID, 327 [0x52] = QUIC_FRAME_INVALID, 328 [0x53] = QUIC_FRAME_INVALID, 329 [0x54] = QUIC_FRAME_INVALID, 330 [0x55] = QUIC_FRAME_INVALID, 331 [0x56] = QUIC_FRAME_INVALID, 332 [0x57] = QUIC_FRAME_INVALID, 333 [0x58] = QUIC_FRAME_INVALID, 334 [0x59] = QUIC_FRAME_INVALID, 335 [0x5A] = QUIC_FRAME_INVALID, 336 [0x5B] = QUIC_FRAME_INVALID, 337 [0x5C] = QUIC_FRAME_INVALID, 338 [0x5D] = QUIC_FRAME_INVALID, 339 [0x5E] = QUIC_FRAME_INVALID, 340 [0x5F] = QUIC_FRAME_INVALID, 341 [0x60] = QUIC_FRAME_INVALID, 342 [0x61] = QUIC_FRAME_INVALID, 343 [0x62] = QUIC_FRAME_INVALID, 344 [0x63] = QUIC_FRAME_INVALID, 345 [0x64] = QUIC_FRAME_INVALID, 346 [0x65] = QUIC_FRAME_INVALID, 347 [0x66] = QUIC_FRAME_INVALID, 348 [0x67] = QUIC_FRAME_INVALID, 349 [0x68] = QUIC_FRAME_INVALID, 350 [0x69] = QUIC_FRAME_INVALID, 351 [0x6A] = QUIC_FRAME_INVALID, 352 [0x6B] = QUIC_FRAME_INVALID, 353 [0x6C] = QUIC_FRAME_INVALID, 354 [0x6D] = QUIC_FRAME_INVALID, 355 [0x6E] = QUIC_FRAME_INVALID, 356 [0x6F] = QUIC_FRAME_INVALID, 357 [0x70] = QUIC_FRAME_INVALID, 358 [0x71] = QUIC_FRAME_INVALID, 359 [0x72] = QUIC_FRAME_INVALID, 360 [0x73] = QUIC_FRAME_INVALID, 361 [0x74] = QUIC_FRAME_INVALID, 362 [0x75] = QUIC_FRAME_INVALID, 363 [0x76] = QUIC_FRAME_INVALID, 364 [0x77] = QUIC_FRAME_INVALID, 365 [0x78] = QUIC_FRAME_INVALID, 366 [0x79] = QUIC_FRAME_INVALID, 367 [0x7A] = QUIC_FRAME_INVALID, 368 [0x7B] = QUIC_FRAME_INVALID, 369 [0x7C] = QUIC_FRAME_INVALID, 370 [0x7D] = QUIC_FRAME_INVALID, 371 [0x7E] = QUIC_FRAME_INVALID, 372 [0x7F] = QUIC_FRAME_INVALID, 373 [0x80] = QUIC_FRAME_INVALID, 374 [0x81] = QUIC_FRAME_INVALID, 375 [0x82] = QUIC_FRAME_INVALID, 376 [0x83] = QUIC_FRAME_INVALID, 377 [0x84] = QUIC_FRAME_INVALID, 378 [0x85] = QUIC_FRAME_INVALID, 379 [0x86] = QUIC_FRAME_INVALID, 380 [0x87] = QUIC_FRAME_INVALID, 381 [0x88] = QUIC_FRAME_INVALID, 382 [0x89] = QUIC_FRAME_INVALID, 383 [0x8A] = QUIC_FRAME_INVALID, 384 [0x8B] = QUIC_FRAME_INVALID, 385 [0x8C] = QUIC_FRAME_INVALID, 386 [0x8D] = QUIC_FRAME_INVALID, 387 [0x8E] = QUIC_FRAME_INVALID, 388 [0x8F] = QUIC_FRAME_INVALID, 389 [0x90] = QUIC_FRAME_INVALID, 390 [0x91] = QUIC_FRAME_INVALID, 391 [0x92] = QUIC_FRAME_INVALID, 392 [0x93] = QUIC_FRAME_INVALID, 393 [0x94] = QUIC_FRAME_INVALID, 394 [0x95] = QUIC_FRAME_INVALID, 395 [0x96] = QUIC_FRAME_INVALID, 396 [0x97] = QUIC_FRAME_INVALID, 397 [0x98] = QUIC_FRAME_INVALID, 398 [0x99] = QUIC_FRAME_INVALID, 399 [0x9A] = QUIC_FRAME_INVALID, 400 [0x9B] = QUIC_FRAME_INVALID, 401 [0x9C] = QUIC_FRAME_INVALID, 402 [0x9D] = QUIC_FRAME_INVALID, 403 [0x9E] = QUIC_FRAME_INVALID, 404 [0x9F] = QUIC_FRAME_INVALID, 405 [0xA0] = QUIC_FRAME_INVALID, 406 [0xA1] = QUIC_FRAME_INVALID, 407 [0xA2] = QUIC_FRAME_INVALID, 408 [0xA3] = QUIC_FRAME_INVALID, 409 [0xA4] = QUIC_FRAME_INVALID, 410 [0xA5] = QUIC_FRAME_INVALID, 411 [0xA6] = QUIC_FRAME_INVALID, 412 [0xA7] = QUIC_FRAME_INVALID, 413 [0xA8] = QUIC_FRAME_INVALID, 414 [0xA9] = QUIC_FRAME_INVALID, 415 [0xAA] = QUIC_FRAME_INVALID, 416 [0xAB] = QUIC_FRAME_INVALID, 417 [0xAC] = QUIC_FRAME_INVALID, 418 [0xAD] = QUIC_FRAME_INVALID, 419 [0xAE] = QUIC_FRAME_INVALID, 420 [0xAF] = QUIC_FRAME_INVALID, 421 [0xB0] = QUIC_FRAME_INVALID, 422 [0xB1] = QUIC_FRAME_INVALID, 423 [0xB2] = QUIC_FRAME_INVALID, 424 [0xB3] = QUIC_FRAME_INVALID, 425 [0xB4] = QUIC_FRAME_INVALID, 426 [0xB5] = QUIC_FRAME_INVALID, 427 [0xB6] = QUIC_FRAME_INVALID, 428 [0xB7] = QUIC_FRAME_INVALID, 429 [0xB8] = QUIC_FRAME_INVALID, 430 [0xB9] = QUIC_FRAME_INVALID, 431 [0xBA] = QUIC_FRAME_INVALID, 432 [0xBB] = QUIC_FRAME_INVALID, 433 [0xBC] = QUIC_FRAME_INVALID, 434 [0xBD] = QUIC_FRAME_INVALID, 435 [0xBE] = QUIC_FRAME_INVALID, 436 [0xBF] = QUIC_FRAME_INVALID, 437 [0xC0] = QUIC_FRAME_INVALID, 438 [0xC1] = QUIC_FRAME_INVALID, 439 [0xC2] = QUIC_FRAME_INVALID, 440 [0xC3] = QUIC_FRAME_INVALID, 441 [0xC4] = QUIC_FRAME_INVALID, 442 [0xC5] = QUIC_FRAME_INVALID, 443 [0xC6] = QUIC_FRAME_INVALID, 444 [0xC7] = QUIC_FRAME_INVALID, 445 [0xC8] = QUIC_FRAME_INVALID, 446 [0xC9] = QUIC_FRAME_INVALID, 447 [0xCA] = QUIC_FRAME_INVALID, 448 [0xCB] = QUIC_FRAME_INVALID, 449 [0xCC] = QUIC_FRAME_INVALID, 450 [0xCD] = QUIC_FRAME_INVALID, 451 [0xCE] = QUIC_FRAME_INVALID, 452 [0xCF] = QUIC_FRAME_INVALID, 453 [0xD0] = QUIC_FRAME_INVALID, 454 [0xD1] = QUIC_FRAME_INVALID, 455 [0xD2] = QUIC_FRAME_INVALID, 456 [0xD3] = QUIC_FRAME_INVALID, 457 [0xD4] = QUIC_FRAME_INVALID, 458 [0xD5] = QUIC_FRAME_INVALID, 459 [0xD6] = QUIC_FRAME_INVALID, 460 [0xD7] = QUIC_FRAME_INVALID, 461 [0xD8] = QUIC_FRAME_INVALID, 462 [0xD9] = QUIC_FRAME_INVALID, 463 [0xDA] = QUIC_FRAME_INVALID, 464 [0xDB] = QUIC_FRAME_INVALID, 465 [0xDC] = QUIC_FRAME_INVALID, 466 [0xDD] = QUIC_FRAME_INVALID, 467 [0xDE] = QUIC_FRAME_INVALID, 468 [0xDF] = QUIC_FRAME_INVALID, 469 [0xE0] = QUIC_FRAME_INVALID, 470 [0xE1] = QUIC_FRAME_INVALID, 471 [0xE2] = QUIC_FRAME_INVALID, 472 [0xE3] = QUIC_FRAME_INVALID, 473 [0xE4] = QUIC_FRAME_INVALID, 474 [0xE5] = QUIC_FRAME_INVALID, 475 [0xE6] = QUIC_FRAME_INVALID, 476 [0xE7] = QUIC_FRAME_INVALID, 477 [0xE8] = QUIC_FRAME_INVALID, 478 [0xE9] = QUIC_FRAME_INVALID, 479 [0xEA] = QUIC_FRAME_INVALID, 480 [0xEB] = QUIC_FRAME_INVALID, 481 [0xEC] = QUIC_FRAME_INVALID, 482 [0xED] = QUIC_FRAME_INVALID, 483 [0xEE] = QUIC_FRAME_INVALID, 484 [0xEF] = QUIC_FRAME_INVALID, 485 [0xF0] = QUIC_FRAME_INVALID, 486 [0xF1] = QUIC_FRAME_INVALID, 487 [0xF2] = QUIC_FRAME_INVALID, 488 [0xF3] = QUIC_FRAME_INVALID, 489 [0xF4] = QUIC_FRAME_INVALID, 490 [0xF5] = QUIC_FRAME_INVALID, 491 [0xF6] = QUIC_FRAME_INVALID, 492 [0xF7] = QUIC_FRAME_INVALID, 493 [0xF8] = QUIC_FRAME_INVALID, 494 [0xF9] = QUIC_FRAME_INVALID, 495 [0xFA] = QUIC_FRAME_INVALID, 496 [0xFB] = QUIC_FRAME_INVALID, 497 [0xFC] = QUIC_FRAME_INVALID, 498 [0xFD] = QUIC_FRAME_INVALID, 499 [0xFE] = QUIC_FRAME_INVALID, 500 [0xFF] = QUIC_FRAME_INVALID, 501}; 502 503 504#if __GNUC__ 505# define popcount __builtin_popcount 506#else 507static int 508popcount (unsigned v) 509{ 510 int count, i; 511 for (i = 0, count = 0; i < sizeof(v) * 8; ++i) 512 if (v & (1 << i)) 513 ++count; 514 return count; 515} 516 517 518#endif 519 520 521int 522lsquic_Q046_gen_ver_nego_pkt (unsigned char *buf, size_t bufsz, 523 const lsquic_cid_t *scid, const lsquic_cid_t *dcid, unsigned versions, 524 uint8_t rand) 525{ 526 unsigned slen, dlen; 527 size_t need; 528 int r; 529 530 need = 1 /* Type */ + 4 /* Packet number */ + 1 /* SCIL */ 531 + scid->len + dcid->len + popcount(versions) * 4; 532 533 if (need > bufsz) 534 return -1; 535 536 *buf++ = 0x80 | 0x40 | rand; 537 memset(buf, 0, 4); 538 buf += 4; 539 540 /* From [draft-ietf-quic-transport-11], Section 4.3: 541 * 542 * The server MUST include the value from the Source Connection ID field 543 * of the packet it receives in the Destination Connection ID field. 544 * The value for Source Connection ID MUST be copied from the 545 * Destination Connection ID of the received packet, which is initially 546 * randomly selected by a client. Echoing both connection IDs gives 547 * clients some assurance that the server received the packet and that 548 * the Version Negotiation packet was not generated by an off-path 549 * attacker. 550 */ 551 552 dlen = dcid->len; 553 if (dlen) 554 dlen -= 3; 555 slen = scid->len; 556 if (slen) 557 slen -= 3; 558 *buf++ = (dlen << 4) | slen; 559 560 memcpy(buf, dcid->idbuf, dcid->len); 561 buf += dcid->len; 562 memcpy(buf, scid->idbuf, scid->len); 563 buf += scid->len; 564 565 r = lsquic_gen_ver_tags(buf, bufsz - 1 - 4 - 1 - dcid->len - scid->len, 566 versions); 567 if (r < 0) 568 return -1; 569 assert((unsigned) r == popcount(versions) * 4u); 570 571 return need; 572} 573 574 575