kopia lustrzana https://github.com/espressif/esp-idf
lwip/test: Add SNTP cases to check NTP timestamp overflow
rodzic
ad0da9cd2b
commit
1f2c16af97
|
@ -13,7 +13,6 @@
|
|||
#include "unity.h"
|
||||
#include "unity_fixture.h"
|
||||
|
||||
#include "unity_test_utils.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#include "lwip/inet.h"
|
||||
|
@ -21,6 +20,7 @@
|
|||
#include "lwip/sockets.h"
|
||||
#include "ping/ping_sock.h"
|
||||
#include "dhcpserver/dhcpserver.h"
|
||||
#include "esp_sntp.h"
|
||||
|
||||
#define ETH_PING_END_BIT BIT(1)
|
||||
#define ETH_PING_DURATION_MS (5000)
|
||||
|
@ -160,11 +160,105 @@ TEST(lwip, dhcp_server_start_stop_localhost)
|
|||
dhcps_delete(dhcps);
|
||||
}
|
||||
|
||||
|
||||
int test_sntp_server_create(void)
|
||||
{
|
||||
struct sockaddr_in dest_addr_ip4;
|
||||
int sock = -1;
|
||||
dest_addr_ip4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
dest_addr_ip4.sin_family = AF_INET;
|
||||
dest_addr_ip4.sin_port = htons(LWIP_IANA_PORT_SNTP);
|
||||
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, sock);
|
||||
int reuse_en = 1;
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_en, sizeof(reuse_en)));
|
||||
TEST_ASSERT_GREATER_OR_EQUAL(0, bind(sock, (struct sockaddr*) &dest_addr_ip4, sizeof(dest_addr_ip4)));
|
||||
return sock;
|
||||
}
|
||||
|
||||
bool test_sntp_server_reply_with_time(int sock, int year, bool msb_flag)
|
||||
{
|
||||
struct sntp_timestamp {
|
||||
uint32_t seconds;
|
||||
uint32_t fraction;
|
||||
};
|
||||
const int SNTP_MSG_LEN = 48;
|
||||
const int SNTP_MODE_CLIENT = 0x03;
|
||||
const int SNTP_MODE_SERVER = 0x04;
|
||||
const int SNTP_MODE_MASK = 0x07;
|
||||
const int SNTP_OFFSET_STRATUM = 1;
|
||||
|
||||
char rx_buffer[SNTP_MSG_LEN];
|
||||
struct sockaddr_storage source_addr;
|
||||
socklen_t socklen = sizeof(source_addr);
|
||||
|
||||
int len = recvfrom(sock, rx_buffer, SNTP_MSG_LEN, 0, (struct sockaddr *)&source_addr, &socklen);
|
||||
if (len == SNTP_MSG_LEN && source_addr.ss_family == PF_INET && (SNTP_MODE_MASK & rx_buffer[0]) == SNTP_MODE_CLIENT) {
|
||||
// modify the client's request to act as a server's response with the injected *xmit* timestamp
|
||||
rx_buffer[0] &= ~SNTP_MODE_CLIENT;
|
||||
rx_buffer[0] |= SNTP_MODE_SERVER;
|
||||
rx_buffer[SNTP_OFFSET_STRATUM] = 0x1;
|
||||
// set the desired timestamp
|
||||
struct sntp_timestamp *timestamp = (struct sntp_timestamp *)(rx_buffer + SNTP_MSG_LEN - sizeof(struct sntp_timestamp)); // xmit is the last timestamp in the datagram
|
||||
int64_t seconds_since_1900 = (365*24*60*60 /* seconds per year */ + 24*60*60/4 /* ~ seconds per leap year */ )*(year-1900);
|
||||
// apply the MSB convention (set: 1968-2036, cleared: 2036-2104)
|
||||
timestamp->seconds = htonl( (msb_flag ? 0x80000000 : 0) | (0xFFFFFFFF & seconds_since_1900) );
|
||||
len = sendto(sock, rx_buffer, SNTP_MSG_LEN, 0, (struct sockaddr *)&source_addr, sizeof(source_addr));
|
||||
if (len == SNTP_MSG_LEN) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void test_sntp_timestamps(int year, bool msb_flag)
|
||||
{
|
||||
int sock = test_sntp_server_create();
|
||||
|
||||
// setup lwip's SNTP in polling mode
|
||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
sntp_setservername(0, "127.0.0.1");
|
||||
sntp_init();
|
||||
|
||||
// wait until time sync
|
||||
int retry = 0;
|
||||
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET) {
|
||||
TEST_ASSERT_TRUE(test_sntp_server_reply_with_time(sock, year, msb_flag)); // post the SNTP server's reply
|
||||
retry++;
|
||||
TEST_ASSERT_LESS_THAN(3, retry);
|
||||
}
|
||||
|
||||
// check time and assert the year
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
TEST_ASSERT_EQUAL(year, 1900 + timeinfo.tm_year);
|
||||
|
||||
// close the SNTP and the fake server
|
||||
sntp_stop();
|
||||
close(sock);
|
||||
}
|
||||
|
||||
TEST(lwip, sntp_client_time_2015)
|
||||
{
|
||||
test_case_uses_tcpip();
|
||||
test_sntp_timestamps(2015, true); // NTP timestamp MSB is set for time before 2036
|
||||
}
|
||||
|
||||
TEST(lwip, sntp_client_time_2048)
|
||||
{
|
||||
test_case_uses_tcpip();
|
||||
test_sntp_timestamps(2048, false); // NTP timestamp MSB is cleared for time after 2036
|
||||
}
|
||||
|
||||
TEST_GROUP_RUNNER(lwip)
|
||||
{
|
||||
RUN_TEST_CASE(lwip, localhost_ping_test)
|
||||
RUN_TEST_CASE(lwip, dhcp_server_init_deinit)
|
||||
RUN_TEST_CASE(lwip, dhcp_server_start_stop_localhost)
|
||||
RUN_TEST_CASE(lwip, sntp_client_time_2015)
|
||||
RUN_TEST_CASE(lwip, sntp_client_time_2048)
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
|
|
Ładowanie…
Reference in New Issue