1 1.2 christos /* $NetBSD: packetHandling.c,v 1.4 2024/08/18 20:47:26 christos Exp $ */ 2 1.2 christos 3 1.1 christos #include "config.h" 4 1.1 christos #include "ntp_debug.h" 5 1.1 christos #include "ntp_stdlib.h" 6 1.1 christos #include "ntp_types.h" 7 1.1 christos 8 1.1 christos #include "sntptest.h" 9 1.1 christos 10 1.1 christos #include "kod_management.h" 11 1.1 christos #include "main.h" 12 1.1 christos #include "networking.h" 13 1.1 christos #include "ntp.h" 14 1.1 christos 15 1.1 christos #include "unity.h" 16 1.1 christos 17 1.2 christos void setUp(void); 18 1.2 christos int LfpEquality(const l_fp expected, const l_fp actual); 19 1.2 christos void test_GenerateUnauthenticatedPacket(void); 20 1.2 christos void test_GenerateAuthenticatedPacket(void); 21 1.2 christos void test_OffsetCalculationPositiveOffset(void); 22 1.2 christos void test_OffsetCalculationNegativeOffset(void); 23 1.2 christos void test_HandleUnusableServer(void); 24 1.2 christos void test_HandleUnusablePacket(void); 25 1.2 christos void test_HandleServerAuthenticationFailure(void); 26 1.2 christos void test_HandleKodDemobilize(void); 27 1.2 christos void test_HandleKodRate(void); 28 1.2 christos void test_HandleCorrectPacket(void); 29 1.1 christos 30 1.1 christos 31 1.2 christos void 32 1.2 christos setUp(void) 33 1.1 christos { 34 1.1 christos init_lib(); 35 1.1 christos } 36 1.1 christos 37 1.1 christos 38 1.2 christos int 39 1.2 christos LfpEquality( 40 1.2 christos const l_fp expected, 41 1.2 christos const l_fp actual 42 1.2 christos ) 43 1.2 christos { 44 1.2 christos return !!(L_ISEQU(&expected, &actual)); 45 1.2 christos } 46 1.1 christos 47 1.1 christos 48 1.2 christos void 49 1.2 christos test_GenerateUnauthenticatedPacket(void) 50 1.2 christos { 51 1.2 christos struct pkt testpkt; 52 1.2 christos struct timeval xmt; 53 1.2 christos l_fp expected_xmt, actual_xmt; 54 1.1 christos 55 1.1 christos GETTIMEOFDAY(&xmt, NULL); 56 1.1 christos xmt.tv_sec += JAN_1970; 57 1.1 christos 58 1.1 christos TEST_ASSERT_EQUAL(LEN_PKT_NOMAC, 59 1.1 christos generate_pkt(&testpkt, &xmt, 0, NULL)); 60 1.1 christos 61 1.1 christos TEST_ASSERT_EQUAL(LEAP_NOTINSYNC, PKT_LEAP(testpkt.li_vn_mode)); 62 1.1 christos TEST_ASSERT_EQUAL(NTP_VERSION, PKT_VERSION(testpkt.li_vn_mode)); 63 1.1 christos TEST_ASSERT_EQUAL(MODE_CLIENT, PKT_MODE(testpkt.li_vn_mode)); 64 1.1 christos 65 1.1 christos TEST_ASSERT_EQUAL(STRATUM_UNSPEC, PKT_TO_STRATUM(testpkt.stratum)); 66 1.1 christos TEST_ASSERT_EQUAL(8, testpkt.ppoll); 67 1.1 christos 68 1.1 christos TVTOTS(&xmt, &expected_xmt); 69 1.1 christos NTOHL_FP(&testpkt.xmt, &actual_xmt); 70 1.1 christos TEST_ASSERT_TRUE(LfpEquality(expected_xmt, actual_xmt)); 71 1.1 christos } 72 1.1 christos 73 1.2 christos 74 1.2 christos void 75 1.2 christos test_GenerateAuthenticatedPacket(void) 76 1.2 christos { 77 1.4 christos #ifdef OPENSSL 78 1.4 christos 79 1.4 christos const int EXPECTED_PKTLEN = LEN_PKT_NOMAC + MAX_SHAKE128_LEN; 80 1.4 christos 81 1.2 christos struct key testkey; 82 1.2 christos struct pkt testpkt; 83 1.2 christos struct timeval xmt; 84 1.2 christos l_fp expected_xmt, actual_xmt; 85 1.4 christos const char key[] = "123456789"; 86 1.4 christos size_t mac_sz; 87 1.4 christos const u_char expected_mac[] = { 88 1.4 christos 0x46, 0x79, 0x81, 0x6b, 89 1.4 christos 0x22, 0xe3, 0xa7, 0xaf, 90 1.4 christos 0x1d, 0x63, 0x20, 0xfb, 91 1.4 christos 0xc7, 0xd6, 0x87, 0x2c 92 1.4 christos }; 93 1.4 christos 94 1.1 christos testkey.next = NULL; 95 1.1 christos testkey.key_id = 30; 96 1.4 christos strlcpy(testkey.key_seq, key, sizeof(testkey.key_seq)); 97 1.4 christos testkey.key_len = strlen(testkey.key_seq); 98 1.4 christos strlcpy(testkey.typen, "SHAKE128", sizeof(testkey.typen)); 99 1.2 christos testkey.typei = keytype_from_text(testkey.typen, NULL); 100 1.1 christos 101 1.4 christos xmt.tv_sec = JAN_1970; 102 1.4 christos xmt.tv_usec = 0; 103 1.1 christos 104 1.1 christos TEST_ASSERT_EQUAL(EXPECTED_PKTLEN, 105 1.4 christos generate_pkt(&testpkt, &xmt, testkey.key_id, 106 1.4 christos &testkey)); 107 1.1 christos 108 1.1 christos TEST_ASSERT_EQUAL(LEAP_NOTINSYNC, PKT_LEAP(testpkt.li_vn_mode)); 109 1.1 christos TEST_ASSERT_EQUAL(NTP_VERSION, PKT_VERSION(testpkt.li_vn_mode)); 110 1.1 christos TEST_ASSERT_EQUAL(MODE_CLIENT, PKT_MODE(testpkt.li_vn_mode)); 111 1.1 christos 112 1.1 christos TEST_ASSERT_EQUAL(STRATUM_UNSPEC, PKT_TO_STRATUM(testpkt.stratum)); 113 1.1 christos TEST_ASSERT_EQUAL(8, testpkt.ppoll); 114 1.1 christos 115 1.1 christos TVTOTS(&xmt, &expected_xmt); 116 1.1 christos NTOHL_FP(&testpkt.xmt, &actual_xmt); 117 1.1 christos TEST_ASSERT_TRUE(LfpEquality(expected_xmt, actual_xmt)); 118 1.1 christos 119 1.1 christos TEST_ASSERT_EQUAL(testkey.key_id, ntohl(testpkt.exten[0])); 120 1.4 christos 121 1.4 christos TEST_ASSERT_EQUAL(sizeof(expected_mac), SHAKE128_LENGTH); 122 1.4 christos mac_sz = make_mac(&testpkt, LEN_PKT_NOMAC, &testkey, 123 1.4 christos &testpkt.exten[1], MAX_MDG_LEN); 124 1.4 christos TEST_ASSERT_EQUAL(mac_sz, SHAKE128_LENGTH); 125 1.4 christos 126 1.4 christos TEST_ASSERT_EQUAL_MEMORY(expected_mac, (void *)&testpkt.exten[1], 127 1.4 christos SHAKE128_LENGTH); 128 1.4 christos 129 1.4 christos #else /* !OPENSSL follows */ 130 1.4 christos 131 1.4 christos TEST_IGNORE_MESSAGE("OpenSSL not found, skipping..."); 132 1.4 christos 133 1.4 christos #endif 134 1.1 christos } 135 1.1 christos 136 1.1 christos 137 1.2 christos void 138 1.2 christos test_OffsetCalculationPositiveOffset(void) 139 1.2 christos { 140 1.2 christos struct pkt rpkt; 141 1.2 christos l_fp reftime, tmp; 142 1.2 christos struct timeval dst; 143 1.2 christos double offset, precision, synch_distance; 144 1.2 christos 145 1.2 christos rpkt.precision = -16; /* 0,000015259 */ 146 1.1 christos rpkt.rootdelay = HTONS_FP(DTOUFP(0.125)); 147 1.1 christos rpkt.rootdisp = HTONS_FP(DTOUFP(0.25)); 148 1.2 christos 149 1.2 christos /* Synch Distance: (0.125+0.25)/2.0 == 0.1875 */ 150 1.1 christos get_systime(&reftime); 151 1.1 christos HTONL_FP(&reftime, &rpkt.reftime); 152 1.1 christos 153 1.2 christos /* T1 - Originate timestamp */ 154 1.1 christos tmp.l_ui = 1000000000UL; 155 1.1 christos tmp.l_uf = 0UL; 156 1.1 christos HTONL_FP(&tmp, &rpkt.org); 157 1.1 christos 158 1.2 christos /* T2 - Receive timestamp */ 159 1.1 christos tmp.l_ui = 1000000001UL; 160 1.1 christos tmp.l_uf = 2147483648UL; 161 1.1 christos HTONL_FP(&tmp, &rpkt.rec); 162 1.1 christos 163 1.2 christos /* T3 - Transmit timestamp */ 164 1.1 christos tmp.l_ui = 1000000002UL; 165 1.1 christos tmp.l_uf = 0UL; 166 1.1 christos HTONL_FP(&tmp, &rpkt.xmt); 167 1.1 christos 168 1.2 christos /* T4 - Destination timestamp as standard timeval */ 169 1.1 christos tmp.l_ui = 1000000001UL; 170 1.1 christos tmp.l_uf = 0UL; 171 1.1 christos TSTOTV(&tmp, &dst); 172 1.1 christos dst.tv_sec -= JAN_1970; 173 1.1 christos 174 1.1 christos offset_calculation(&rpkt, LEN_PKT_NOMAC, &dst, &offset, &precision, &synch_distance); 175 1.1 christos 176 1.2 christos TEST_ASSERT_EQUAL_DOUBLE(1.25, offset); 177 1.2 christos TEST_ASSERT_EQUAL_DOUBLE(1. / ULOGTOD(16), precision); 178 1.2 christos /* 1.1250150000000001 ? */ 179 1.2 christos TEST_ASSERT_EQUAL_DOUBLE(1.125015, synch_distance); 180 1.1 christos } 181 1.1 christos 182 1.2 christos 183 1.2 christos void 184 1.2 christos test_OffsetCalculationNegativeOffset(void) 185 1.2 christos { 186 1.2 christos struct pkt rpkt; 187 1.2 christos l_fp reftime, tmp; 188 1.2 christos struct timeval dst; 189 1.2 christos double offset, precision, synch_distance; 190 1.1 christos 191 1.1 christos rpkt.precision = -1; 192 1.1 christos rpkt.rootdelay = HTONS_FP(DTOUFP(0.5)); 193 1.1 christos rpkt.rootdisp = HTONS_FP(DTOUFP(0.5)); 194 1.4 christos 195 1.2 christos /* Synch Distance is (0.5+0.5)/2.0, or 0.5 */ 196 1.1 christos get_systime(&reftime); 197 1.1 christos HTONL_FP(&reftime, &rpkt.reftime); 198 1.1 christos 199 1.2 christos /* T1 - Originate timestamp */ 200 1.1 christos tmp.l_ui = 1000000001UL; 201 1.1 christos tmp.l_uf = 0UL; 202 1.1 christos HTONL_FP(&tmp, &rpkt.org); 203 1.1 christos 204 1.2 christos /* T2 - Receive timestamp */ 205 1.1 christos tmp.l_ui = 1000000000UL; 206 1.1 christos tmp.l_uf = 2147483648UL; 207 1.1 christos HTONL_FP(&tmp, &rpkt.rec); 208 1.1 christos 209 1.2 christos /*/ T3 - Transmit timestamp */ 210 1.1 christos tmp.l_ui = 1000000001UL; 211 1.1 christos tmp.l_uf = 2147483648UL; 212 1.1 christos HTONL_FP(&tmp, &rpkt.xmt); 213 1.1 christos 214 1.2 christos /* T4 - Destination timestamp as standard timeval */ 215 1.1 christos tmp.l_ui = 1000000003UL; 216 1.1 christos tmp.l_uf = 0UL; 217 1.2 christos 218 1.1 christos TSTOTV(&tmp, &dst); 219 1.1 christos dst.tv_sec -= JAN_1970; 220 1.1 christos 221 1.1 christos offset_calculation(&rpkt, LEN_PKT_NOMAC, &dst, &offset, &precision, &synch_distance); 222 1.1 christos 223 1.2 christos TEST_ASSERT_EQUAL_DOUBLE(-1, offset); 224 1.2 christos TEST_ASSERT_EQUAL_DOUBLE(1. / ULOGTOD(1), precision); 225 1.2 christos TEST_ASSERT_EQUAL_DOUBLE(1.3333483333333334, synch_distance); 226 1.1 christos } 227 1.1 christos 228 1.2 christos 229 1.2 christos void 230 1.2 christos test_HandleUnusableServer(void) 231 1.2 christos { 232 1.2 christos struct pkt rpkt; 233 1.1 christos sockaddr_u host; 234 1.1 christos int rpktl; 235 1.1 christos 236 1.1 christos ZERO(rpkt); 237 1.1 christos ZERO(host); 238 1.1 christos rpktl = SERVER_UNUSEABLE; 239 1.1 christos TEST_ASSERT_EQUAL(-1, handle_pkt(rpktl, &rpkt, &host, "")); 240 1.1 christos } 241 1.1 christos 242 1.2 christos 243 1.2 christos void 244 1.2 christos test_HandleUnusablePacket(void) 245 1.2 christos { 246 1.2 christos struct pkt rpkt; 247 1.1 christos sockaddr_u host; 248 1.1 christos int rpktl; 249 1.1 christos 250 1.1 christos ZERO(rpkt); 251 1.1 christos ZERO(host); 252 1.1 christos rpktl = PACKET_UNUSEABLE; 253 1.1 christos TEST_ASSERT_EQUAL(1, handle_pkt(rpktl, &rpkt, &host, "")); 254 1.1 christos } 255 1.1 christos 256 1.2 christos 257 1.2 christos void 258 1.2 christos test_HandleServerAuthenticationFailure(void) 259 1.2 christos { 260 1.2 christos struct pkt rpkt; 261 1.1 christos sockaddr_u host; 262 1.1 christos int rpktl; 263 1.1 christos 264 1.1 christos ZERO(rpkt); 265 1.1 christos ZERO(host); 266 1.1 christos rpktl = SERVER_AUTH_FAIL; 267 1.1 christos TEST_ASSERT_EQUAL(1, handle_pkt(rpktl, &rpkt, &host, "")); 268 1.1 christos } 269 1.1 christos 270 1.2 christos 271 1.2 christos void 272 1.2 christos test_HandleKodDemobilize(void) 273 1.2 christos { 274 1.2 christos static const char * HOSTNAME = "192.0.2.1"; 275 1.2 christos static const char * REASON = "DENY"; 276 1.1 christos struct pkt rpkt; 277 1.2 christos sockaddr_u host; 278 1.2 christos int rpktl; 279 1.1 christos struct kod_entry * entry; 280 1.1 christos 281 1.1 christos rpktl = KOD_DEMOBILIZE; 282 1.1 christos ZERO(rpkt); 283 1.1 christos memcpy(&rpkt.refid, REASON, 4); 284 1.1 christos ZERO(host); 285 1.1 christos host.sa4.sin_family = AF_INET; 286 1.1 christos host.sa4.sin_addr.s_addr = inet_addr(HOSTNAME); 287 1.1 christos 288 1.2 christos /* Test that the KOD-entry is added to the database. */ 289 1.1 christos kod_init_kod_db("/dev/null", TRUE); 290 1.1 christos 291 1.1 christos TEST_ASSERT_EQUAL(1, handle_pkt(rpktl, &rpkt, &host, HOSTNAME)); 292 1.1 christos 293 1.1 christos TEST_ASSERT_EQUAL(1, search_entry(HOSTNAME, &entry)); 294 1.2 christos TEST_ASSERT_EQUAL_MEMORY(REASON, entry->type, 4); 295 1.1 christos } 296 1.1 christos 297 1.2 christos 298 1.2 christos void 299 1.2 christos test_HandleKodRate(void) 300 1.2 christos { 301 1.2 christos struct pkt rpkt; 302 1.1 christos sockaddr_u host; 303 1.1 christos int rpktl; 304 1.1 christos 305 1.1 christos ZERO(rpkt); 306 1.1 christos ZERO(host); 307 1.1 christos rpktl = KOD_RATE; 308 1.1 christos TEST_ASSERT_EQUAL(1, handle_pkt(rpktl, &rpkt, &host, "")); 309 1.1 christos } 310 1.1 christos 311 1.2 christos 312 1.2 christos void 313 1.2 christos test_HandleCorrectPacket(void) 314 1.2 christos { 315 1.2 christos struct pkt rpkt; 316 1.1 christos sockaddr_u host; 317 1.1 christos int rpktl; 318 1.1 christos l_fp now; 319 1.1 christos 320 1.2 christos /* We don't want our testing code to actually change the system clock. */ 321 1.1 christos TEST_ASSERT_FALSE(ENABLED_OPT(STEP)); 322 1.1 christos TEST_ASSERT_FALSE(ENABLED_OPT(SLEW)); 323 1.1 christos 324 1.1 christos get_systime(&now); 325 1.1 christos HTONL_FP(&now, &rpkt.reftime); 326 1.1 christos HTONL_FP(&now, &rpkt.org); 327 1.1 christos HTONL_FP(&now, &rpkt.rec); 328 1.1 christos HTONL_FP(&now, &rpkt.xmt); 329 1.1 christos rpktl = LEN_PKT_NOMAC; 330 1.1 christos ZERO(host); 331 1.1 christos AF(&host) = AF_INET; 332 1.1 christos 333 1.1 christos TEST_ASSERT_EQUAL(0, handle_pkt(rpktl, &rpkt, &host, "")); 334 1.1 christos } 335 1.1 christos 336 1.1 christos /* packetHandling.c */ 337