/* $NetBSD: packetHandling.c,v 1.4 2024/08/18 20:47:26 christos Exp $ */ #include "config.h" #include "ntp_debug.h" #include "ntp_stdlib.h" #include "ntp_types.h" #include "sntptest.h" #include "kod_management.h" #include "main.h" #include "networking.h" #include "ntp.h" #include "unity.h" void setUp(void); int LfpEquality(const l_fp expected, const l_fp actual); void test_GenerateUnauthenticatedPacket(void); void test_GenerateAuthenticatedPacket(void); void test_OffsetCalculationPositiveOffset(void); void test_OffsetCalculationNegativeOffset(void); void test_HandleUnusableServer(void); void test_HandleUnusablePacket(void); void test_HandleServerAuthenticationFailure(void); void test_HandleKodDemobilize(void); void test_HandleKodRate(void); void test_HandleCorrectPacket(void); void setUp(void) { init_lib(); } int LfpEquality( const l_fp expected, const l_fp actual ) { return !!(L_ISEQU(&expected, &actual)); } void test_GenerateUnauthenticatedPacket(void) { struct pkt testpkt; struct timeval xmt; l_fp expected_xmt, actual_xmt; GETTIMEOFDAY(&xmt, NULL); xmt.tv_sec += JAN_1970; TEST_ASSERT_EQUAL(LEN_PKT_NOMAC, generate_pkt(&testpkt, &xmt, 0, NULL)); TEST_ASSERT_EQUAL(LEAP_NOTINSYNC, PKT_LEAP(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(NTP_VERSION, PKT_VERSION(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(MODE_CLIENT, PKT_MODE(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(STRATUM_UNSPEC, PKT_TO_STRATUM(testpkt.stratum)); TEST_ASSERT_EQUAL(8, testpkt.ppoll); TVTOTS(&xmt, &expected_xmt); NTOHL_FP(&testpkt.xmt, &actual_xmt); TEST_ASSERT_TRUE(LfpEquality(expected_xmt, actual_xmt)); } void test_GenerateAuthenticatedPacket(void) { #ifdef OPENSSL const int EXPECTED_PKTLEN = LEN_PKT_NOMAC + MAX_SHAKE128_LEN; struct key testkey; struct pkt testpkt; struct timeval xmt; l_fp expected_xmt, actual_xmt; const char key[] = "123456789"; size_t mac_sz; const u_char expected_mac[] = { 0x46, 0x79, 0x81, 0x6b, 0x22, 0xe3, 0xa7, 0xaf, 0x1d, 0x63, 0x20, 0xfb, 0xc7, 0xd6, 0x87, 0x2c }; testkey.next = NULL; testkey.key_id = 30; strlcpy(testkey.key_seq, key, sizeof(testkey.key_seq)); testkey.key_len = strlen(testkey.key_seq); strlcpy(testkey.typen, "SHAKE128", sizeof(testkey.typen)); testkey.typei = keytype_from_text(testkey.typen, NULL); xmt.tv_sec = JAN_1970; xmt.tv_usec = 0; TEST_ASSERT_EQUAL(EXPECTED_PKTLEN, generate_pkt(&testpkt, &xmt, testkey.key_id, &testkey)); TEST_ASSERT_EQUAL(LEAP_NOTINSYNC, PKT_LEAP(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(NTP_VERSION, PKT_VERSION(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(MODE_CLIENT, PKT_MODE(testpkt.li_vn_mode)); TEST_ASSERT_EQUAL(STRATUM_UNSPEC, PKT_TO_STRATUM(testpkt.stratum)); TEST_ASSERT_EQUAL(8, testpkt.ppoll); TVTOTS(&xmt, &expected_xmt); NTOHL_FP(&testpkt.xmt, &actual_xmt); TEST_ASSERT_TRUE(LfpEquality(expected_xmt, actual_xmt)); TEST_ASSERT_EQUAL(testkey.key_id, ntohl(testpkt.exten[0])); TEST_ASSERT_EQUAL(sizeof(expected_mac), SHAKE128_LENGTH); mac_sz = make_mac(&testpkt, LEN_PKT_NOMAC, &testkey, &testpkt.exten[1], MAX_MDG_LEN); TEST_ASSERT_EQUAL(mac_sz, SHAKE128_LENGTH); TEST_ASSERT_EQUAL_MEMORY(expected_mac, (void *)&testpkt.exten[1], SHAKE128_LENGTH); #else /* !OPENSSL follows */ TEST_IGNORE_MESSAGE("OpenSSL not found, skipping..."); #endif } void test_OffsetCalculationPositiveOffset(void) { struct pkt rpkt; l_fp reftime, tmp; struct timeval dst; double offset, precision, synch_distance; rpkt.precision = -16; /* 0,000015259 */ rpkt.rootdelay = HTONS_FP(DTOUFP(0.125)); rpkt.rootdisp = HTONS_FP(DTOUFP(0.25)); /* Synch Distance: (0.125+0.25)/2.0 == 0.1875 */ get_systime(&reftime); HTONL_FP(&reftime, &rpkt.reftime); /* T1 - Originate timestamp */ tmp.l_ui = 1000000000UL; tmp.l_uf = 0UL; HTONL_FP(&tmp, &rpkt.org); /* T2 - Receive timestamp */ tmp.l_ui = 1000000001UL; tmp.l_uf = 2147483648UL; HTONL_FP(&tmp, &rpkt.rec); /* T3 - Transmit timestamp */ tmp.l_ui = 1000000002UL; tmp.l_uf = 0UL; HTONL_FP(&tmp, &rpkt.xmt); /* T4 - Destination timestamp as standard timeval */ tmp.l_ui = 1000000001UL; tmp.l_uf = 0UL; TSTOTV(&tmp, &dst); dst.tv_sec -= JAN_1970; offset_calculation(&rpkt, LEN_PKT_NOMAC, &dst, &offset, &precision, &synch_distance); TEST_ASSERT_EQUAL_DOUBLE(1.25, offset); TEST_ASSERT_EQUAL_DOUBLE(1. / ULOGTOD(16), precision); /* 1.1250150000000001 ? */ TEST_ASSERT_EQUAL_DOUBLE(1.125015, synch_distance); } void test_OffsetCalculationNegativeOffset(void) { struct pkt rpkt; l_fp reftime, tmp; struct timeval dst; double offset, precision, synch_distance; rpkt.precision = -1; rpkt.rootdelay = HTONS_FP(DTOUFP(0.5)); rpkt.rootdisp = HTONS_FP(DTOUFP(0.5)); /* Synch Distance is (0.5+0.5)/2.0, or 0.5 */ get_systime(&reftime); HTONL_FP(&reftime, &rpkt.reftime); /* T1 - Originate timestamp */ tmp.l_ui = 1000000001UL; tmp.l_uf = 0UL; HTONL_FP(&tmp, &rpkt.org); /* T2 - Receive timestamp */ tmp.l_ui = 1000000000UL; tmp.l_uf = 2147483648UL; HTONL_FP(&tmp, &rpkt.rec); /*/ T3 - Transmit timestamp */ tmp.l_ui = 1000000001UL; tmp.l_uf = 2147483648UL; HTONL_FP(&tmp, &rpkt.xmt); /* T4 - Destination timestamp as standard timeval */ tmp.l_ui = 1000000003UL; tmp.l_uf = 0UL; TSTOTV(&tmp, &dst); dst.tv_sec -= JAN_1970; offset_calculation(&rpkt, LEN_PKT_NOMAC, &dst, &offset, &precision, &synch_distance); TEST_ASSERT_EQUAL_DOUBLE(-1, offset); TEST_ASSERT_EQUAL_DOUBLE(1. / ULOGTOD(1), precision); TEST_ASSERT_EQUAL_DOUBLE(1.3333483333333334, synch_distance); } void test_HandleUnusableServer(void) { struct pkt rpkt; sockaddr_u host; int rpktl; ZERO(rpkt); ZERO(host); rpktl = SERVER_UNUSEABLE; TEST_ASSERT_EQUAL(-1, handle_pkt(rpktl, &rpkt, &host, "")); } void test_HandleUnusablePacket(void) { struct pkt rpkt; sockaddr_u host; int rpktl; ZERO(rpkt); ZERO(host); rpktl = PACKET_UNUSEABLE; TEST_ASSERT_EQUAL(1, handle_pkt(rpktl, &rpkt, &host, "")); } void test_HandleServerAuthenticationFailure(void) { struct pkt rpkt; sockaddr_u host; int rpktl; ZERO(rpkt); ZERO(host); rpktl = SERVER_AUTH_FAIL; TEST_ASSERT_EQUAL(1, handle_pkt(rpktl, &rpkt, &host, "")); } void test_HandleKodDemobilize(void) { static const char * HOSTNAME = "192.0.2.1"; static const char * REASON = "DENY"; struct pkt rpkt; sockaddr_u host; int rpktl; struct kod_entry * entry; rpktl = KOD_DEMOBILIZE; ZERO(rpkt); memcpy(&rpkt.refid, REASON, 4); ZERO(host); host.sa4.sin_family = AF_INET; host.sa4.sin_addr.s_addr = inet_addr(HOSTNAME); /* Test that the KOD-entry is added to the database. */ kod_init_kod_db("/dev/null", TRUE); TEST_ASSERT_EQUAL(1, handle_pkt(rpktl, &rpkt, &host, HOSTNAME)); TEST_ASSERT_EQUAL(1, search_entry(HOSTNAME, &entry)); TEST_ASSERT_EQUAL_MEMORY(REASON, entry->type, 4); } void test_HandleKodRate(void) { struct pkt rpkt; sockaddr_u host; int rpktl; ZERO(rpkt); ZERO(host); rpktl = KOD_RATE; TEST_ASSERT_EQUAL(1, handle_pkt(rpktl, &rpkt, &host, "")); } void test_HandleCorrectPacket(void) { struct pkt rpkt; sockaddr_u host; int rpktl; l_fp now; /* We don't want our testing code to actually change the system clock. */ TEST_ASSERT_FALSE(ENABLED_OPT(STEP)); TEST_ASSERT_FALSE(ENABLED_OPT(SLEW)); get_systime(&now); HTONL_FP(&now, &rpkt.reftime); HTONL_FP(&now, &rpkt.org); HTONL_FP(&now, &rpkt.rec); HTONL_FP(&now, &rpkt.xmt); rpktl = LEN_PKT_NOMAC; ZERO(host); AF(&host) = AF_INET; TEST_ASSERT_EQUAL(0, handle_pkt(rpktl, &rpkt, &host, "")); } /* packetHandling.c */