ngtcp2_transport_params.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886
  1. /*
  2. * ngtcp2
  3. *
  4. * Copyright (c) 2023 ngtcp2 contributors
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining
  7. * a copy of this software and associated documentation files (the
  8. * "Software"), to deal in the Software without restriction, including
  9. * without limitation the rights to use, copy, modify, merge, publish,
  10. * distribute, sublicense, and/or sell copies of the Software, and to
  11. * permit persons to whom the Software is furnished to do so, subject to
  12. * the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  21. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24. */
  25. #include "ngtcp2_transport_params.h"
  26. #include <string.h>
  27. #include <assert.h>
  28. #include "ngtcp2_conv.h"
  29. #include "ngtcp2_str.h"
  30. #include "ngtcp2_mem.h"
  31. #include "ngtcp2_unreachable.h"
  32. void ngtcp2_transport_params_default_versioned(
  33. int transport_params_version, ngtcp2_transport_params *params) {
  34. size_t len;
  35. switch (transport_params_version) {
  36. case NGTCP2_TRANSPORT_PARAMS_VERSION:
  37. len = sizeof(*params);
  38. break;
  39. default:
  40. ngtcp2_unreachable();
  41. }
  42. memset(params, 0, len);
  43. switch (transport_params_version) {
  44. case NGTCP2_TRANSPORT_PARAMS_VERSION:
  45. params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE;
  46. params->active_connection_id_limit =
  47. NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
  48. params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
  49. params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
  50. break;
  51. }
  52. }
  53. /*
  54. * varint_paramlen returns the length of a single transport parameter
  55. * which has variable integer in its parameter.
  56. */
  57. static size_t varint_paramlen(ngtcp2_transport_param_id id, uint64_t param) {
  58. size_t valuelen = ngtcp2_put_uvarintlen(param);
  59. return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(valuelen) + valuelen;
  60. }
  61. /*
  62. * write_varint_param writes parameter |id| of the given |value| in
  63. * varint encoding. It returns p + the number of bytes written.
  64. */
  65. static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id,
  66. uint64_t value) {
  67. p = ngtcp2_put_uvarint(p, id);
  68. p = ngtcp2_put_uvarint(p, ngtcp2_put_uvarintlen(value));
  69. return ngtcp2_put_uvarint(p, value);
  70. }
  71. /*
  72. * zero_paramlen returns the length of a single transport parameter
  73. * which has zero length value in its parameter.
  74. */
  75. static size_t zero_paramlen(ngtcp2_transport_param_id id) {
  76. return ngtcp2_put_uvarintlen(id) + 1;
  77. }
  78. /*
  79. * write_zero_param writes parameter |id| that has zero length value.
  80. * It returns p + the number of bytes written.
  81. */
  82. static uint8_t *write_zero_param(uint8_t *p, ngtcp2_transport_param_id id) {
  83. p = ngtcp2_put_uvarint(p, id);
  84. *p++ = 0;
  85. return p;
  86. }
  87. /*
  88. * cid_paramlen returns the length of a single transport parameter
  89. * which has |cid| as value.
  90. */
  91. static size_t cid_paramlen(ngtcp2_transport_param_id id,
  92. const ngtcp2_cid *cid) {
  93. return ngtcp2_put_uvarintlen(id) + ngtcp2_put_uvarintlen(cid->datalen) +
  94. cid->datalen;
  95. }
  96. /*
  97. * write_cid_param writes parameter |id| of the given |cid|. It
  98. * returns p + the number of bytes written.
  99. */
  100. static uint8_t *write_cid_param(uint8_t *p, ngtcp2_transport_param_id id,
  101. const ngtcp2_cid *cid) {
  102. assert(cid->datalen == 0 || cid->datalen >= NGTCP2_MIN_CIDLEN);
  103. assert(cid->datalen <= NGTCP2_MAX_CIDLEN);
  104. p = ngtcp2_put_uvarint(p, id);
  105. p = ngtcp2_put_uvarint(p, cid->datalen);
  106. if (cid->datalen) {
  107. p = ngtcp2_cpymem(p, cid->data, cid->datalen);
  108. }
  109. return p;
  110. }
  111. static const uint8_t empty_address[16];
  112. ngtcp2_ssize ngtcp2_transport_params_encode_versioned(
  113. uint8_t *dest, size_t destlen, int transport_params_version,
  114. const ngtcp2_transport_params *params) {
  115. uint8_t *p;
  116. size_t len = 0;
  117. /* For some reason, gcc 7.3.0 requires this initialization. */
  118. size_t preferred_addrlen = 0;
  119. size_t version_infolen = 0;
  120. const ngtcp2_sockaddr_in *sa_in;
  121. const ngtcp2_sockaddr_in6 *sa_in6;
  122. ngtcp2_transport_params paramsbuf;
  123. params = ngtcp2_transport_params_convert_to_latest(
  124. &paramsbuf, transport_params_version, params);
  125. if (params->original_dcid_present) {
  126. len +=
  127. cid_paramlen(NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
  128. &params->original_dcid);
  129. }
  130. if (params->stateless_reset_token_present) {
  131. len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN) +
  132. ngtcp2_put_uvarintlen(NGTCP2_STATELESS_RESET_TOKENLEN) +
  133. NGTCP2_STATELESS_RESET_TOKENLEN;
  134. }
  135. if (params->preferred_addr_present) {
  136. assert(params->preferred_addr.cid.datalen >= NGTCP2_MIN_CIDLEN);
  137. assert(params->preferred_addr.cid.datalen <= NGTCP2_MAX_CIDLEN);
  138. preferred_addrlen = 4 /* ipv4Address */ + 2 /* ipv4Port */ +
  139. 16 /* ipv6Address */ + 2 /* ipv6Port */
  140. + 1 + params->preferred_addr.cid.datalen /* CID */ +
  141. NGTCP2_STATELESS_RESET_TOKENLEN;
  142. len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS) +
  143. ngtcp2_put_uvarintlen(preferred_addrlen) + preferred_addrlen;
  144. }
  145. if (params->retry_scid_present) {
  146. len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
  147. &params->retry_scid);
  148. }
  149. if (params->initial_scid_present) {
  150. len += cid_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
  151. &params->initial_scid);
  152. }
  153. if (params->initial_max_stream_data_bidi_local) {
  154. len +=
  155. varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
  156. params->initial_max_stream_data_bidi_local);
  157. }
  158. if (params->initial_max_stream_data_bidi_remote) {
  159. len += varint_paramlen(
  160. NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
  161. params->initial_max_stream_data_bidi_remote);
  162. }
  163. if (params->initial_max_stream_data_uni) {
  164. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
  165. params->initial_max_stream_data_uni);
  166. }
  167. if (params->initial_max_data) {
  168. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
  169. params->initial_max_data);
  170. }
  171. if (params->initial_max_streams_bidi) {
  172. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
  173. params->initial_max_streams_bidi);
  174. }
  175. if (params->initial_max_streams_uni) {
  176. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
  177. params->initial_max_streams_uni);
  178. }
  179. if (params->max_udp_payload_size !=
  180. NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
  181. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
  182. params->max_udp_payload_size);
  183. }
  184. if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
  185. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
  186. params->ack_delay_exponent);
  187. }
  188. if (params->disable_active_migration) {
  189. len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION);
  190. }
  191. if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
  192. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
  193. params->max_ack_delay / NGTCP2_MILLISECONDS);
  194. }
  195. if (params->max_idle_timeout) {
  196. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
  197. params->max_idle_timeout / NGTCP2_MILLISECONDS);
  198. }
  199. if (params->active_connection_id_limit &&
  200. params->active_connection_id_limit !=
  201. NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
  202. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
  203. params->active_connection_id_limit);
  204. }
  205. if (params->max_datagram_frame_size) {
  206. len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
  207. params->max_datagram_frame_size);
  208. }
  209. if (params->grease_quic_bit) {
  210. len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT);
  211. }
  212. if (params->version_info_present) {
  213. version_infolen =
  214. sizeof(uint32_t) + params->version_info.available_versionslen;
  215. len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION) +
  216. ngtcp2_put_uvarintlen(version_infolen) + version_infolen;
  217. }
  218. if (dest == NULL && destlen == 0) {
  219. return (ngtcp2_ssize)len;
  220. }
  221. if (destlen < len) {
  222. return NGTCP2_ERR_NOBUF;
  223. }
  224. p = dest;
  225. if (params->original_dcid_present) {
  226. p = write_cid_param(
  227. p, NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID,
  228. &params->original_dcid);
  229. }
  230. if (params->stateless_reset_token_present) {
  231. p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN);
  232. p = ngtcp2_put_uvarint(p, sizeof(params->stateless_reset_token));
  233. p = ngtcp2_cpymem(p, params->stateless_reset_token,
  234. sizeof(params->stateless_reset_token));
  235. }
  236. if (params->preferred_addr_present) {
  237. p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS);
  238. p = ngtcp2_put_uvarint(p, preferred_addrlen);
  239. if (params->preferred_addr.ipv4_present) {
  240. sa_in = &params->preferred_addr.ipv4;
  241. p = ngtcp2_cpymem(p, &sa_in->sin_addr, sizeof(sa_in->sin_addr));
  242. p = ngtcp2_put_uint16(p, sa_in->sin_port);
  243. } else {
  244. p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in->sin_addr));
  245. p = ngtcp2_put_uint16(p, 0);
  246. }
  247. if (params->preferred_addr.ipv6_present) {
  248. sa_in6 = &params->preferred_addr.ipv6;
  249. p = ngtcp2_cpymem(p, &sa_in6->sin6_addr, sizeof(sa_in6->sin6_addr));
  250. p = ngtcp2_put_uint16(p, sa_in6->sin6_port);
  251. } else {
  252. p = ngtcp2_cpymem(p, empty_address, sizeof(sa_in6->sin6_addr));
  253. p = ngtcp2_put_uint16(p, 0);
  254. }
  255. *p++ = (uint8_t)params->preferred_addr.cid.datalen;
  256. if (params->preferred_addr.cid.datalen) {
  257. p = ngtcp2_cpymem(p, params->preferred_addr.cid.data,
  258. params->preferred_addr.cid.datalen);
  259. }
  260. p = ngtcp2_cpymem(p, params->preferred_addr.stateless_reset_token,
  261. sizeof(params->preferred_addr.stateless_reset_token));
  262. }
  263. if (params->retry_scid_present) {
  264. p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID,
  265. &params->retry_scid);
  266. }
  267. if (params->initial_scid_present) {
  268. p = write_cid_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID,
  269. &params->initial_scid);
  270. }
  271. if (params->initial_max_stream_data_bidi_local) {
  272. p = write_varint_param(
  273. p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL,
  274. params->initial_max_stream_data_bidi_local);
  275. }
  276. if (params->initial_max_stream_data_bidi_remote) {
  277. p = write_varint_param(
  278. p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE,
  279. params->initial_max_stream_data_bidi_remote);
  280. }
  281. if (params->initial_max_stream_data_uni) {
  282. p =
  283. write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI,
  284. params->initial_max_stream_data_uni);
  285. }
  286. if (params->initial_max_data) {
  287. p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA,
  288. params->initial_max_data);
  289. }
  290. if (params->initial_max_streams_bidi) {
  291. p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI,
  292. params->initial_max_streams_bidi);
  293. }
  294. if (params->initial_max_streams_uni) {
  295. p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI,
  296. params->initial_max_streams_uni);
  297. }
  298. if (params->max_udp_payload_size !=
  299. NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE) {
  300. p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE,
  301. params->max_udp_payload_size);
  302. }
  303. if (params->ack_delay_exponent != NGTCP2_DEFAULT_ACK_DELAY_EXPONENT) {
  304. p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT,
  305. params->ack_delay_exponent);
  306. }
  307. if (params->disable_active_migration) {
  308. p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION);
  309. }
  310. if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) {
  311. p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY,
  312. params->max_ack_delay / NGTCP2_MILLISECONDS);
  313. }
  314. if (params->max_idle_timeout) {
  315. p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT,
  316. params->max_idle_timeout / NGTCP2_MILLISECONDS);
  317. }
  318. if (params->active_connection_id_limit &&
  319. params->active_connection_id_limit !=
  320. NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT) {
  321. p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT,
  322. params->active_connection_id_limit);
  323. }
  324. if (params->max_datagram_frame_size) {
  325. p = write_varint_param(p, NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE,
  326. params->max_datagram_frame_size);
  327. }
  328. if (params->grease_quic_bit) {
  329. p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT);
  330. }
  331. if (params->version_info_present) {
  332. p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION);
  333. p = ngtcp2_put_uvarint(p, version_infolen);
  334. p = ngtcp2_put_uint32be(p, params->version_info.chosen_version);
  335. if (params->version_info.available_versionslen) {
  336. p = ngtcp2_cpymem(p, params->version_info.available_versions,
  337. params->version_info.available_versionslen);
  338. }
  339. }
  340. assert((size_t)(p - dest) == len);
  341. return (ngtcp2_ssize)len;
  342. }
  343. /*
  344. * decode_varint decodes a single varint from the buffer pointed by
  345. * |*pp| of length |end - *pp|. If it decodes an integer
  346. * successfully, it stores the integer in |*pdest|, increment |*pp| by
  347. * the number of bytes read from |*pp|, and returns 0. Otherwise it
  348. * returns -1.
  349. */
  350. static int decode_varint(uint64_t *pdest, const uint8_t **pp,
  351. const uint8_t *end) {
  352. const uint8_t *p = *pp;
  353. size_t len;
  354. if (p == end) {
  355. return -1;
  356. }
  357. len = ngtcp2_get_uvarintlen(p);
  358. if ((uint64_t)(end - p) < len) {
  359. return -1;
  360. }
  361. *pp = ngtcp2_get_uvarint(pdest, p);
  362. return 0;
  363. }
  364. /*
  365. * decode_varint_param decodes length prefixed value from the buffer
  366. * pointed by |*pp| of length |end - *pp|. The length and value are
  367. * encoded in varint form. If it decodes a value successfully, it
  368. * stores the value in |*pdest|, increment |*pp| by the number of
  369. * bytes read from |*pp|, and returns 0. Otherwise it returns -1.
  370. */
  371. static int decode_varint_param(uint64_t *pdest, const uint8_t **pp,
  372. const uint8_t *end) {
  373. const uint8_t *p = *pp;
  374. uint64_t valuelen;
  375. if (decode_varint(&valuelen, &p, end) != 0) {
  376. return -1;
  377. }
  378. if (p == end) {
  379. return -1;
  380. }
  381. if ((uint64_t)(end - p) < valuelen) {
  382. return -1;
  383. }
  384. if (ngtcp2_get_uvarintlen(p) != valuelen) {
  385. return -1;
  386. }
  387. *pp = ngtcp2_get_uvarint(pdest, p);
  388. return 0;
  389. }
  390. /*
  391. * decode_zero_param decodes zero length value from the buffer pointed
  392. * by |*pp| of length |end - *pp|. The length is encoded in varint
  393. * form. If it decodes zero length value successfully, it increments
  394. * |*pp| by 1, and returns 0. Otherwise it returns -1.
  395. */
  396. static int decode_zero_param(const uint8_t **pp, const uint8_t *end) {
  397. if (*pp == end || **pp != 0) {
  398. return -1;
  399. }
  400. ++*pp;
  401. return 0;
  402. }
  403. /*
  404. * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer
  405. * pointed by |*pp| of length |end - *pp|. The length is encoded in
  406. * varint form. If it decodes a value successfully, it stores the
  407. * value in |*pdest|, increment |*pp| by the number of read from
  408. * |*pp|, and returns the number of bytes read. Otherwise it returns
  409. * the one of the negative error code:
  410. *
  411. * NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM
  412. * Could not decode Connection ID.
  413. */
  414. static int decode_cid_param(ngtcp2_cid *pdest, const uint8_t **pp,
  415. const uint8_t *end) {
  416. const uint8_t *p = *pp;
  417. uint64_t valuelen;
  418. if (decode_varint(&valuelen, &p, end) != 0) {
  419. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  420. }
  421. if ((valuelen != 0 && valuelen < NGTCP2_MIN_CIDLEN) ||
  422. valuelen > NGTCP2_MAX_CIDLEN || (size_t)(end - p) < valuelen) {
  423. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  424. }
  425. ngtcp2_cid_init(pdest, p, (size_t)valuelen);
  426. p += valuelen;
  427. *pp = p;
  428. return 0;
  429. }
  430. int ngtcp2_transport_params_decode_versioned(int transport_params_version,
  431. ngtcp2_transport_params *dest,
  432. const uint8_t *data,
  433. size_t datalen) {
  434. const uint8_t *p, *end, *lend;
  435. size_t len;
  436. uint64_t param_type;
  437. uint64_t valuelen;
  438. int rv;
  439. ngtcp2_sockaddr_in *sa_in;
  440. ngtcp2_sockaddr_in6 *sa_in6;
  441. uint32_t version;
  442. ngtcp2_transport_params *params, paramsbuf;
  443. if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) {
  444. params = dest;
  445. } else {
  446. params = &paramsbuf;
  447. }
  448. /* Set default values */
  449. memset(params, 0, sizeof(*params));
  450. params->max_udp_payload_size = NGTCP2_DEFAULT_MAX_RECV_UDP_PAYLOAD_SIZE;
  451. params->ack_delay_exponent = NGTCP2_DEFAULT_ACK_DELAY_EXPONENT;
  452. params->max_ack_delay = NGTCP2_DEFAULT_MAX_ACK_DELAY;
  453. params->active_connection_id_limit =
  454. NGTCP2_DEFAULT_ACTIVE_CONNECTION_ID_LIMIT;
  455. p = data;
  456. end = data + datalen;
  457. for (; (size_t)(end - p) >= 2;) {
  458. if (decode_varint(&param_type, &p, end) != 0) {
  459. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  460. }
  461. switch (param_type) {
  462. case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL:
  463. if (decode_varint_param(&params->initial_max_stream_data_bidi_local, &p,
  464. end) != 0) {
  465. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  466. }
  467. break;
  468. case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE:
  469. if (decode_varint_param(&params->initial_max_stream_data_bidi_remote, &p,
  470. end) != 0) {
  471. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  472. }
  473. break;
  474. case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAM_DATA_UNI:
  475. if (decode_varint_param(&params->initial_max_stream_data_uni, &p, end) !=
  476. 0) {
  477. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  478. }
  479. break;
  480. case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_DATA:
  481. if (decode_varint_param(&params->initial_max_data, &p, end) != 0) {
  482. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  483. }
  484. break;
  485. case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_BIDI:
  486. if (decode_varint_param(&params->initial_max_streams_bidi, &p, end) !=
  487. 0) {
  488. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  489. }
  490. if (params->initial_max_streams_bidi > NGTCP2_MAX_STREAMS) {
  491. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  492. }
  493. break;
  494. case NGTCP2_TRANSPORT_PARAM_INITIAL_MAX_STREAMS_UNI:
  495. if (decode_varint_param(&params->initial_max_streams_uni, &p, end) != 0) {
  496. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  497. }
  498. if (params->initial_max_streams_uni > NGTCP2_MAX_STREAMS) {
  499. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  500. }
  501. break;
  502. case NGTCP2_TRANSPORT_PARAM_MAX_IDLE_TIMEOUT:
  503. if (decode_varint_param(&params->max_idle_timeout, &p, end) != 0) {
  504. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  505. }
  506. params->max_idle_timeout *= NGTCP2_MILLISECONDS;
  507. break;
  508. case NGTCP2_TRANSPORT_PARAM_MAX_UDP_PAYLOAD_SIZE:
  509. if (decode_varint_param(&params->max_udp_payload_size, &p, end) != 0) {
  510. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  511. }
  512. break;
  513. case NGTCP2_TRANSPORT_PARAM_STATELESS_RESET_TOKEN:
  514. if (decode_varint(&valuelen, &p, end) != 0) {
  515. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  516. }
  517. if ((size_t)valuelen != sizeof(params->stateless_reset_token)) {
  518. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  519. }
  520. if ((size_t)(end - p) < sizeof(params->stateless_reset_token)) {
  521. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  522. }
  523. p = ngtcp2_get_bytes(params->stateless_reset_token, p,
  524. sizeof(params->stateless_reset_token));
  525. params->stateless_reset_token_present = 1;
  526. break;
  527. case NGTCP2_TRANSPORT_PARAM_ACK_DELAY_EXPONENT:
  528. if (decode_varint_param(&params->ack_delay_exponent, &p, end) != 0) {
  529. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  530. }
  531. if (params->ack_delay_exponent > 20) {
  532. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  533. }
  534. break;
  535. case NGTCP2_TRANSPORT_PARAM_PREFERRED_ADDRESS:
  536. if (decode_varint(&valuelen, &p, end) != 0) {
  537. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  538. }
  539. if ((size_t)(end - p) < valuelen) {
  540. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  541. }
  542. len = 4 /* ipv4Address */ + 2 /* ipv4Port */ + 16 /* ipv6Address */ +
  543. 2 /* ipv6Port */
  544. + 1 /* cid length */ + NGTCP2_STATELESS_RESET_TOKENLEN;
  545. if (valuelen < len) {
  546. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  547. }
  548. sa_in = &params->preferred_addr.ipv4;
  549. p = ngtcp2_get_bytes(&sa_in->sin_addr, p, sizeof(sa_in->sin_addr));
  550. p = ngtcp2_get_uint16(&sa_in->sin_port, p);
  551. if (sa_in->sin_port || memcmp(empty_address, &sa_in->sin_addr,
  552. sizeof(sa_in->sin_addr)) != 0) {
  553. sa_in->sin_family = NGTCP2_AF_INET;
  554. params->preferred_addr.ipv4_present = 1;
  555. }
  556. sa_in6 = &params->preferred_addr.ipv6;
  557. p = ngtcp2_get_bytes(&sa_in6->sin6_addr, p, sizeof(sa_in6->sin6_addr));
  558. p = ngtcp2_get_uint16(&sa_in6->sin6_port, p);
  559. if (sa_in6->sin6_port || memcmp(empty_address, &sa_in6->sin6_addr,
  560. sizeof(sa_in6->sin6_addr)) != 0) {
  561. sa_in6->sin6_family = NGTCP2_AF_INET6;
  562. params->preferred_addr.ipv6_present = 1;
  563. }
  564. /* cid */
  565. params->preferred_addr.cid.datalen = *p++;
  566. len += params->preferred_addr.cid.datalen;
  567. if (valuelen != len ||
  568. params->preferred_addr.cid.datalen > NGTCP2_MAX_CIDLEN ||
  569. params->preferred_addr.cid.datalen < NGTCP2_MIN_CIDLEN) {
  570. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  571. }
  572. if (params->preferred_addr.cid.datalen) {
  573. p = ngtcp2_get_bytes(params->preferred_addr.cid.data, p,
  574. params->preferred_addr.cid.datalen);
  575. }
  576. /* stateless reset token */
  577. p =
  578. ngtcp2_get_bytes(params->preferred_addr.stateless_reset_token, p,
  579. sizeof(params->preferred_addr.stateless_reset_token));
  580. params->preferred_addr_present = 1;
  581. break;
  582. case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION:
  583. if (decode_zero_param(&p, end) != 0) {
  584. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  585. }
  586. params->disable_active_migration = 1;
  587. break;
  588. case NGTCP2_TRANSPORT_PARAM_ORIGINAL_DESTINATION_CONNECTION_ID:
  589. rv = decode_cid_param(&params->original_dcid, &p, end);
  590. if (rv != 0) {
  591. return rv;
  592. }
  593. params->original_dcid_present = 1;
  594. break;
  595. case NGTCP2_TRANSPORT_PARAM_RETRY_SOURCE_CONNECTION_ID:
  596. rv = decode_cid_param(&params->retry_scid, &p, end);
  597. if (rv != 0) {
  598. return rv;
  599. }
  600. params->retry_scid_present = 1;
  601. break;
  602. case NGTCP2_TRANSPORT_PARAM_INITIAL_SOURCE_CONNECTION_ID:
  603. rv = decode_cid_param(&params->initial_scid, &p, end);
  604. if (rv != 0) {
  605. return rv;
  606. }
  607. params->initial_scid_present = 1;
  608. break;
  609. case NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY:
  610. if (decode_varint_param(&params->max_ack_delay, &p, end) != 0) {
  611. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  612. }
  613. if (params->max_ack_delay >= 16384) {
  614. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  615. }
  616. params->max_ack_delay *= NGTCP2_MILLISECONDS;
  617. break;
  618. case NGTCP2_TRANSPORT_PARAM_ACTIVE_CONNECTION_ID_LIMIT:
  619. if (decode_varint_param(&params->active_connection_id_limit, &p, end) !=
  620. 0) {
  621. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  622. }
  623. break;
  624. case NGTCP2_TRANSPORT_PARAM_MAX_DATAGRAM_FRAME_SIZE:
  625. if (decode_varint_param(&params->max_datagram_frame_size, &p, end) != 0) {
  626. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  627. }
  628. break;
  629. case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT:
  630. if (decode_zero_param(&p, end) != 0) {
  631. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  632. }
  633. params->grease_quic_bit = 1;
  634. break;
  635. case NGTCP2_TRANSPORT_PARAM_VERSION_INFORMATION:
  636. if (decode_varint(&valuelen, &p, end) != 0) {
  637. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  638. }
  639. if ((size_t)(end - p) < valuelen) {
  640. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  641. }
  642. if (valuelen < sizeof(uint32_t) || (valuelen & 0x3)) {
  643. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  644. }
  645. p = ngtcp2_get_uint32be(&params->version_info.chosen_version, p);
  646. if (params->version_info.chosen_version == 0) {
  647. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  648. }
  649. if (valuelen > sizeof(uint32_t)) {
  650. params->version_info.available_versions = (uint8_t *)p;
  651. params->version_info.available_versionslen =
  652. (size_t)valuelen - sizeof(uint32_t);
  653. for (lend = p + (valuelen - sizeof(uint32_t)); p != lend;) {
  654. p = ngtcp2_get_uint32be(&version, p);
  655. if (version == 0) {
  656. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  657. }
  658. }
  659. }
  660. params->version_info_present = 1;
  661. break;
  662. default:
  663. /* Ignore unknown parameter */
  664. if (decode_varint(&valuelen, &p, end) != 0) {
  665. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  666. }
  667. if ((size_t)(end - p) < valuelen) {
  668. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  669. }
  670. p += valuelen;
  671. break;
  672. }
  673. }
  674. if (end - p != 0) {
  675. return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM;
  676. }
  677. if (transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION) {
  678. ngtcp2_transport_params_convert_to_old(transport_params_version, dest,
  679. params);
  680. }
  681. return 0;
  682. }
  683. static int transport_params_copy_new(ngtcp2_transport_params **pdest,
  684. const ngtcp2_transport_params *src,
  685. const ngtcp2_mem *mem) {
  686. size_t len = sizeof(**pdest);
  687. ngtcp2_transport_params *dest;
  688. uint8_t *p;
  689. if (src->version_info_present) {
  690. len += src->version_info.available_versionslen;
  691. }
  692. dest = ngtcp2_mem_malloc(mem, len);
  693. if (dest == NULL) {
  694. return NGTCP2_ERR_NOMEM;
  695. }
  696. *dest = *src;
  697. if (src->version_info_present && src->version_info.available_versionslen) {
  698. p = (uint8_t *)dest + sizeof(*dest);
  699. memcpy(p, src->version_info.available_versions,
  700. src->version_info.available_versionslen);
  701. dest->version_info.available_versions = p;
  702. }
  703. *pdest = dest;
  704. return 0;
  705. }
  706. int ngtcp2_transport_params_decode_new(ngtcp2_transport_params **pparams,
  707. const uint8_t *data, size_t datalen,
  708. const ngtcp2_mem *mem) {
  709. int rv;
  710. ngtcp2_transport_params params;
  711. rv = ngtcp2_transport_params_decode(&params, data, datalen);
  712. if (rv < 0) {
  713. return rv;
  714. }
  715. if (mem == NULL) {
  716. mem = ngtcp2_mem_default();
  717. }
  718. return transport_params_copy_new(pparams, &params, mem);
  719. }
  720. void ngtcp2_transport_params_del(ngtcp2_transport_params *params,
  721. const ngtcp2_mem *mem) {
  722. if (params == NULL) {
  723. return;
  724. }
  725. if (mem == NULL) {
  726. mem = ngtcp2_mem_default();
  727. }
  728. ngtcp2_mem_free(mem, params);
  729. }
  730. int ngtcp2_transport_params_copy_new(ngtcp2_transport_params **pdest,
  731. const ngtcp2_transport_params *src,
  732. const ngtcp2_mem *mem) {
  733. if (src == NULL) {
  734. *pdest = NULL;
  735. return 0;
  736. }
  737. return transport_params_copy_new(pdest, src, mem);
  738. }
  739. static void transport_params_copy(ngtcp2_transport_params *dest,
  740. const ngtcp2_transport_params *src,
  741. int transport_params_version) {
  742. assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION);
  743. switch (transport_params_version) {
  744. case NGTCP2_TRANSPORT_PARAMS_V1:
  745. memcpy(dest, src,
  746. offsetof(ngtcp2_transport_params, version_info_present) +
  747. sizeof(src->version_info_present));
  748. break;
  749. }
  750. }
  751. const ngtcp2_transport_params *
  752. ngtcp2_transport_params_convert_to_latest(ngtcp2_transport_params *dest,
  753. int transport_params_version,
  754. const ngtcp2_transport_params *src) {
  755. if (transport_params_version == NGTCP2_TRANSPORT_PARAMS_VERSION) {
  756. return src;
  757. }
  758. ngtcp2_transport_params_default(dest);
  759. transport_params_copy(dest, src, transport_params_version);
  760. return dest;
  761. }
  762. void ngtcp2_transport_params_convert_to_old(
  763. int transport_params_version, ngtcp2_transport_params *dest,
  764. const ngtcp2_transport_params *src) {
  765. assert(transport_params_version != NGTCP2_TRANSPORT_PARAMS_VERSION);
  766. transport_params_copy(dest, src, transport_params_version);
  767. }