diff --git a/convert.h b/convert.h index 5981139..fb2065f 100644 --- a/convert.h +++ b/convert.h @@ -94,7 +94,7 @@ struct convert_supported_opts { struct convert_cookie { struct convert_tlv tlv_hdr; uint16_t reserved; - uint32_t opaque[0]; + uint8_t opaque[0]; } __attribute__((packed)); struct convert_error { diff --git a/convert_util.c b/convert_util.c index 8a078f2..8ec725f 100644 --- a/convert_util.c +++ b/convert_util.c @@ -60,6 +60,7 @@ void convert_free_opts(struct convert_opts *opts) { free(opts->tcp_options); + free(opts->cookie_data); free(opts); } @@ -147,6 +148,22 @@ convert_parse_tlvs(const uint8_t *buff, size_t buff_len) break; } + case CONVERT_COOKIE: { + struct convert_cookie *cookie = + (struct convert_cookie *)buff; + size_t cookie_len = + tlv_len - sizeof(struct convert_cookie); + + opts->flags |= CONVERT_F_COOKIE; + + opts->cookie_len = cookie_len; + opts->cookie_data = malloc(cookie_len); + if (opts->cookie_data == NULL) + goto error_and_free; + memcpy(opts->cookie_data, cookie->opaque, cookie_len); + + break; + } /* TODO support other TLVs. */ default: goto error_and_free; diff --git a/convert_util.h b/convert_util.h index 8a09750..fedf6af 100644 --- a/convert_util.h +++ b/convert_util.h @@ -84,6 +84,10 @@ struct convert_opts { uint8_t * tcp_options; size_t tcp_options_len; + /* if CONVERT_F_COOKIE is set in flags */ + uint8_t * cookie_data; + size_t cookie_len; + /* TODO extend to support more TLVs. */ }; diff --git a/tests/check_convert_util.c b/tests/check_convert_util.c index 53ed98b..5f06840 100644 --- a/tests/check_convert_util.c +++ b/tests/check_convert_util.c @@ -85,6 +85,25 @@ sample_convert_tcp_ext_hdr_tlv(size_t *len) return ext_tcp_hdr; } +struct convert_cookie * +sample_convert_cookie_tlv(size_t *len) +{ + unsigned int i = 0; + size_t cookie_len = 8; + + *len = sizeof(struct convert_cookie) + cookie_len; + struct convert_cookie * cookie = malloc(*len); + struct convert_tlv * tlv = (struct convert_tlv *)cookie; + + tlv->length = 3; /* In 32-bit words */ + tlv->type = CONVERT_COOKIE; + cookie->reserved = 0; + for (i = 0; i < cookie_len; i++) + cookie->opaque[i] = rand() % 256; + + return cookie; +} + START_TEST (test_convert_parse_header) { int ret; struct convert_header hdr; @@ -236,6 +255,37 @@ START_TEST (test_convert_parse_tlvs_ext_tcp_hdr) { } END_TEST +START_TEST (test_convert_parse_tlvs_cookie) { + struct convert_opts * opts; + uint8_t * buff; + size_t buff_len; + struct convert_cookie * cookie; + unsigned int i; + size_t cookie_len; + + buff = (uint8_t *)sample_convert_cookie_tlv(&buff_len); + cookie = (struct convert_cookie *)buff; + + opts = convert_parse_tlvs(buff, sizeof(struct convert_cookie) - 1); + ck_assert_msg(opts == NULL, + "Should fail: buff len shorter than Cookie TLV"); + + opts = convert_parse_tlvs(buff, buff_len); + ck_assert_msg(opts != NULL, "Should parse valid Convert Cookie TLV"); + ck_assert_msg(opts->flags & CONVERT_F_COOKIE, "Should set COOKIE flag"); + + cookie_len = buff_len - sizeof(struct convert_cookie); + ck_assert_msg(opts->cookie_len == cookie_len, "Should set cookie_len"); + + for (i = 0; i < cookie_len; ++i) + ck_assert_msg(opts->cookie_data[i] == cookie->opaque[i], + "Should return exact copy TCP options"); + + convert_free_opts(opts); + free(buff); +} +END_TEST + START_TEST (test_convert_parse_tlvs_multiple) { struct convert_opts * opts; uint8_t * buff; @@ -322,6 +372,7 @@ convert_util_suite(void) tcase_add_test(tc_core, test_convert_parse_tlvs_connect); tcase_add_test(tc_core, test_convert_parse_tlvs_error); tcase_add_test(tc_core, test_convert_parse_tlvs_ext_tcp_hdr); + tcase_add_test(tc_core, test_convert_parse_tlvs_cookie); tcase_add_test(tc_core, test_convert_parse_tlvs_multiple); tcase_add_test(tc_core, test_convert_write_tlvs); /* TODO: