1/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 2#include <assert.h> 3#include <stdio.h> 4#include <stdlib.h> 5#include <string.h> 6#include <sys/queue.h> 7#ifndef WIN32 8#include <sys/time.h> 9#endif 10 11#include "lsquic.h" 12#include "lsquic_types.h" 13#include "lsquic_packet_common.h" 14#include "lsquic_parse.h" 15#include "lsquic_parse_common.h" 16#include "lsquic_mm.h" 17#include "lsquic_packet_in.h" 18#include "lsquic_engine_public.h" 19#include "lsquic_version.h" 20 21 22/* The struct is used to test both generation and parsing of version 23 * negotiation packet. 24 */ 25struct gen_ver_nego_test { 26 int gvnt_lineno; 27 /* Generate: inputs; parse: outputs */ 28 enum lsquic_version 29 gvnt_gen_ver; 30 uint64_t gvnt_cid; 31 unsigned gvnt_versions; 32 size_t gvnt_bufsz; 33 /* Generate: outputs; parse: inputs */ 34 int gvnt_len; /* Retval */ 35 char gvnt_buf[0x40]; /* Contents */ 36}; 37 38 39static const struct gen_ver_nego_test tests[] = { 40 41 { .gvnt_lineno = __LINE__, 42 .gvnt_cid = 0x0102030405060708UL, 43 .gvnt_versions = (1 << LSQVER_043), 44 .gvnt_gen_ver = LSQVER_043, 45 .gvnt_bufsz = 12, 46 .gvnt_len = -1, /* Buffer size is too small */ 47 }, 48 49 { .gvnt_lineno = __LINE__, 50 .gvnt_cid = 0x0102030405060708UL, 51 .gvnt_versions = (1 << LSQVER_043) | (1 << N_LSQVER), 52 .gvnt_gen_ver = LSQVER_043, 53 .gvnt_bufsz = 20, 54 .gvnt_len = -1, /* Invalid version specified in the bitmask */ 55 }, 56 57 { .gvnt_lineno = __LINE__, 58 .gvnt_cid = 0x0102030405060708UL, 59 .gvnt_versions = (1 << LSQVER_043) | (1 << LSQVER_046), 60 .gvnt_gen_ver = LSQVER_043, 61 .gvnt_bufsz = 17, 62 .gvnt_len = 17, 63 .gvnt_buf = { 64 PACKET_PUBLIC_FLAGS_VERSION| 65 PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID, 66 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Connection ID */ 67 'Q', '0', '4', '3', 68 'Q', '0', '4', '6', 69 }, 70 }, 71 72}; 73 74 75static void 76test_parsing_ver_nego (const struct gen_ver_nego_test *gvnt) 77{ 78 int s; 79 lsquic_packet_in_t *packet_in; 80 struct lsquic_mm mm; 81 struct ver_iter vi; 82 lsquic_ver_tag_t ver_tag; 83 enum lsquic_version version; 84 struct packin_parse_state ppstate; 85 unsigned version_bitmask = gvnt->gvnt_versions; 86 87 lsquic_mm_init(&mm); 88 packet_in = lsquic_mm_get_packet_in(&mm); 89 packet_in->pi_data = lsquic_mm_get_packet_in_buf(&mm, 1370); 90 packet_in->pi_flags |= PI_OWN_DATA; 91 memcpy(packet_in->pi_data, gvnt->gvnt_buf, gvnt->gvnt_len); 92 s = lsquic_parse_packet_in_begin(packet_in, gvnt->gvnt_len, 0, GQUIC_CID_LEN, &ppstate); 93 assert(s == 0); 94 95 for (s = lsquic_packet_in_ver_first(packet_in, &vi, &ver_tag); s; 96 s = lsquic_packet_in_ver_next(&vi, &ver_tag)) 97 { 98 version = lsquic_tag2ver(ver_tag); 99 assert(version < N_LSQVER); 100 assert(version_bitmask & (1 << version)); 101 version_bitmask &= ~(1 << version); 102 } 103 104 assert(0 == version_bitmask); 105 106 lsquic_mm_put_packet_in(&mm, packet_in); 107 lsquic_mm_cleanup(&mm); 108} 109 110 111static void 112run_gvnt (int i) 113{ 114 const struct gen_ver_nego_test *const gvnt = &tests[i]; 115 lsquic_cid_t scid, dcid; 116 int len; 117 118 memset(&dcid, 0, sizeof(dcid)); 119 dcid.len = sizeof(gvnt->gvnt_cid); 120 memcpy(dcid.idbuf, &gvnt->gvnt_cid, sizeof(gvnt->gvnt_cid)); 121 122 unsigned char out[0x40]; 123 assert(sizeof(out) <= sizeof(gvnt->gvnt_buf)); /* Internal sanity check */ 124 125 if ((1 << gvnt->gvnt_gen_ver) & LSQUIC_GQUIC_HEADER_VERSIONS) 126 len = lsquic_gquic_gen_ver_nego_pkt(out, gvnt->gvnt_bufsz, &dcid, 127 gvnt->gvnt_versions); 128 else 129 { 130 /* XXX this is never executed, as there is no test case for this */ 131 scid = (lsquic_cid_t) { .len = 0, }; 132 len = lsquic_Q046_gen_ver_nego_pkt(out, gvnt->gvnt_bufsz, &dcid, 133 &scid, gvnt->gvnt_versions, ((unsigned char) rand()) & 0xF); 134 } 135 assert(("Packet length is correct", len == gvnt->gvnt_len)); 136 137 if (gvnt->gvnt_len > 0) 138 { 139 if ((1 << gvnt->gvnt_gen_ver) & LSQUIC_GQUIC_HEADER_VERSIONS) 140 assert(("Packet contents are correct", 141 0 == memcmp(out, gvnt->gvnt_buf, gvnt->gvnt_len))); 142 else 143 { 144 assert(("Packet contents are correct", 145 0 == memcmp(out + 1, gvnt->gvnt_buf + 1, gvnt->gvnt_len - 1))); 146 assert(out[0] & 0x80); /* Other 7 bits are random */ 147 } 148 test_parsing_ver_nego(gvnt); 149 } 150} 151 152 153int 154main (void) 155{ 156 unsigned i; 157 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i) 158 run_gvnt(i); 159 return 0; 160} 161