/* ********************************************************************** * Copyright (C) Miroslav Lichvar 2020 * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ********************************************************************** */ #include #include "test.h" #ifdef FEAT_NTP #include #include #include void test_unit(void) { unsigned char *buffer, body[NTP_MAX_EXTENSIONS_LENGTH]; void *bodyp; NTP_PacketInfo info; NTP_Packet packet; int i, j, start, length, type, type2, body_length, body_length2; assert(sizeof (uint16_t) == 2); assert(sizeof (body) == sizeof (packet.extensions)); buffer = (unsigned char *)packet.extensions; for (i = 0; i < 10000; i++) { body_length = random() % (sizeof (body) - 4 + 1) / 4 * 4; start = random() % (sizeof (packet.extensions) - body_length - 4 + 1) / 4 * 4; type = random() % 0x10000; DEBUG_LOG("body_length=%d start=%d type=%d", body_length, start, type); assert(body_length + start <= sizeof (packet.extensions)); UTI_GetRandomBytes(body, body_length); TEST_CHECK(!NEF_SetField(buffer, body_length + start + 4, start, type, body, body_length + 4, &length)); TEST_CHECK(!NEF_SetField(buffer, body_length + start + 4, start + 4, type, body, body_length, &length)); TEST_CHECK(!NEF_SetField(buffer, body_length + start + 4, start, type, body, body_length - 1, &length)); TEST_CHECK(!NEF_SetField(buffer, body_length + start + 4, start, type, body, body_length - 2, &length)); TEST_CHECK(!NEF_SetField(buffer, body_length + start + 4, start, type, body, body_length - 3, &length)); TEST_CHECK(!NEF_SetField(buffer, body_length + start + 3, start, type, body, body_length, &length)); TEST_CHECK(!NEF_SetField(buffer, body_length + start + 5, start + 1, type, body, body_length, &length)); TEST_CHECK(NEF_SetField(buffer, body_length + start + 4, start, type, body, body_length, &length)); TEST_CHECK(length == body_length + 4); TEST_CHECK(((uint16_t *)buffer)[start / 2] == htons(type)); TEST_CHECK(((uint16_t *)buffer)[start / 2 + 1] == htons(length)); TEST_CHECK(memcmp(buffer + start + 4, body, body_length) == 0); memset(&packet, 0, sizeof (packet)); packet.lvm = NTP_LVM(0, 4, MODE_CLIENT); memset(&info, 0, sizeof (info)); info.version = 3; info.length = NTP_HEADER_LENGTH; TEST_CHECK(!NEF_AddBlankField(&packet, &info, type, body_length, &bodyp)); info.version = 4; info.length = NTP_HEADER_LENGTH - 4; TEST_CHECK(!NEF_AddBlankField(&packet, &info, type, body_length, &bodyp)); info.length = sizeof (packet) - body_length; TEST_CHECK(!NEF_AddBlankField(&packet, &info, type, body_length, &bodyp)); info.length = NTP_HEADER_LENGTH + start; if (body_length < 12) { TEST_CHECK(!NEF_AddBlankField(&packet, &info, type, body_length, &bodyp)); continue; } TEST_CHECK(NEF_AddBlankField(&packet, &info, type, body_length, &bodyp)); TEST_CHECK(info.length == NTP_HEADER_LENGTH + start + body_length + 4); TEST_CHECK(((uint16_t *)buffer)[start / 2] == htons(type)); TEST_CHECK(((uint16_t *)buffer)[start / 2 + 1] == htons(length)); TEST_CHECK(bodyp == buffer + start + 4); TEST_CHECK(info.ext_fields == 1); memset(buffer, 0, sizeof (packet.extensions)); info.length = NTP_HEADER_LENGTH + start; info.ext_fields = 0; TEST_CHECK(NEF_AddField(&packet, &info, type, body, body_length)); TEST_CHECK(info.length == NTP_HEADER_LENGTH + start + body_length + 4); TEST_CHECK(((uint16_t *)buffer)[start / 2] == htons(type)); TEST_CHECK(((uint16_t *)buffer)[start / 2 + 1] == htons(length)); TEST_CHECK(memcmp(buffer + start + 4, body, body_length) == 0); TEST_CHECK(info.ext_fields == 1); for (j = 1; j <= 4; j++) { TEST_CHECK(((uint16_t *)buffer)[start / 2 + 1] = htons(length + j)); TEST_CHECK(!NEF_ParseSingleField(buffer, start + body_length + 4, start, &length, &type2, &bodyp, &body_length2)); } TEST_CHECK(((uint16_t *)buffer)[start / 2 + 1] = htons(length)); TEST_CHECK(NEF_ParseSingleField(buffer, sizeof (packet.extensions), start, &length, &type2, &bodyp, &body_length2)); TEST_CHECK(length == body_length + 4); TEST_CHECK(type2 == type); TEST_CHECK(bodyp == buffer + start + 4); TEST_CHECK(body_length2 == body_length); TEST_CHECK(!NEF_ParseField(&packet, sizeof (packet) + 4, NTP_HEADER_LENGTH + start, &length, &type2, &bodyp, &body_length2)); if (body_length < 24) { TEST_CHECK(!NEF_ParseField(&packet, NTP_HEADER_LENGTH + start + length, NTP_HEADER_LENGTH + start, &length, &type2, &bodyp, &body_length2)); if (sizeof (packet.extensions) - start <= 24) { TEST_CHECK(!NEF_ParseField(&packet, sizeof (packet), NTP_HEADER_LENGTH + start, &length, &type2, &bodyp, &body_length2)); continue; } else { TEST_CHECK(NEF_ParseField(&packet, sizeof (packet), NTP_HEADER_LENGTH + start, &length, &type2, &bodyp, &body_length2)); } } else { TEST_CHECK(NEF_ParseField(&packet, NTP_HEADER_LENGTH + start + length, NTP_HEADER_LENGTH + start, &length, &type2, &bodyp, &body_length2)); } TEST_CHECK(length == body_length + 4); TEST_CHECK(type2 == type); TEST_CHECK(bodyp == buffer + start + 4); TEST_CHECK(body_length2 == body_length); } } #else void test_unit(void) { TEST_REQUIRE(0); } #endif