Skip to content

Conversation

@lfelten
Copy link
Contributor

@lfelten lfelten commented Sep 15, 2025

Implementation of SNTP server functionality (RFC 5905)

Zephyr software example is also provided.

Comment on lines +119 to +124
ret = sendto(data->sock, &sntp_reply, sizeof(struct sntp_pkt), 0, &client_addr,
client_addr_len);

Check failure

Code scanning / SonarCloud

POSIX functions should not be called with arguments that trigger buffer overflows High

"sendto" overflows read buffer "&sntp\_reply"; passed size "sizeof(struct snt..." (2304) exceeds buffer size (48) See more on SonarQube Cloud
Implementation of SNTP server functionality (RFC 5905) Zephyr software example is also provided. Signed-off-by: Lothar Felten <lothar.felten@gmail.com>
@pdgendt
Copy link
Contributor

pdgendt commented Sep 16, 2025

@jukkar can probably comment on this, but shouldn't we use a socket service for this?

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
E Security Rating on New Code (required ≥ C)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

char recv_buffer[SNTP_SERVER_RX_BUFFER_SIZE];
};

static struct sntp_pkt sntp_reply;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why having a global reply buffer as this prevents multiple threads to send data at the same time? Can't we allocate this from stack in each receive function?

return ret;
}

static void sntp_udp4_thread(void)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could use socket service API here to avoid these IPv4 and IPv6 threads and save some memory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I'll look into the socket service API and I'll rewrite the code.

@jukkar
Copy link
Member

jukkar commented Sep 16, 2025

can probably comment on this, but shouldn't we use a socket service for this?

Yes, I think so. Noticed your comment after giving mine about the same issue.

Comment on lines +146 to +147
while (ret == 0) {
sntp_process_packet(&data_ipv4);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

infinite loop

Suggested change
while (ret == 0) {
sntp_process_packet(&data_ipv4);
while (ret == 0) {
ret = sntp_process_packet(&data_ipv4);
endif # SNTP client

config SNTP_SERVER
bool "SNTP client support"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool "SNTP client support"
bool "SNTP server support"
sntp_reply.orig_tm_s = pkt->tx_tm_s;
sntp_reply.orig_tm_f = pkt->tx_tm_f;
sntp_reply.rx_tm_s = htonl(systime.tv_sec + OFFSET_1970_JAN_1);
sntp_reply.rx_tm_f = htonl((systime.tv_nsec));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NTP timestamps use a 32-bit fractional second in units of 2⁻³² seconds, not nanoseconds.
Need to convert, something like:

uint32_t frac = (uint32_t)((((uint64_t)systime.tv_nsec) << 32) / 1000000000ULL); sntp_reply.rx_tm_f = htonl(frac);
return ret;
}
sntp_reply.tx_tm_s = htonl(systime.tv_sec + OFFSET_1970_JAN_1);
sntp_reply.tx_tm_f = htonl((systime.tv_nsec));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

return 0;
}
tp.tv_sec = t.seconds;
tp.tv_nsec = t.fraction / 1000;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again, wrong handling of the fractional part, I think

@kartben kartben requested a review from Copilot September 16, 2025 09:03
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements SNTP server functionality (RFC 5905) with automatic IPv4/IPv6 thread management and includes a complete example application.

  • Introduces SNTP server library that can handle client time requests on both IPv4 and IPv6
  • Refactors existing SNTP code to separate client and server components with shared constants
  • Provides configuration options for server thread stack size and priority

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
subsys/net/lib/sntp/sntp_server.c Core SNTP server implementation with packet processing and socket handling
subsys/net/lib/sntp/sntp_pkt.h Shared SNTP constants moved from client code
subsys/net/lib/sntp/sntp.c Refactored to use shared constants and make packet dump function public
subsys/net/lib/sntp/Kconfig Configuration options for SNTP client/server separation
subsys/net/lib/sntp/CMakeLists.txt Build system updates for conditional compilation
samples/net/sockets/sntp_server/* Complete example application demonstrating SNTP server usage
samples/net/cloud/aws_iot_mqtt/prj.conf Updated to use new SNTP_CLIENT config
include/zephyr/net/sntp_server.h Public API header for SNTP server functionality

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

sntp_reply.li = SNTP_LEAP_INDICATOR_CLOCK_INVALID;
sntp_reply.mode = SNTP_MODE_SERVER;
sntp_reply.stratum = SNTP_STRATUM_KOD;
sntp_reply.mode = SNTP_MODE_SERVER;
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate assignment of sntp_reply.mode on line 48 and 50. Remove the redundant assignment on line 50.

Suggested change
sntp_reply.mode = SNTP_MODE_SERVER;
Copilot uses AI. Check for mistakes.
sntp_reply.mode = SNTP_MODE_SERVER;
sntp_reply.stratum = SNTP_STRATUM_KOD;
sntp_reply.mode = SNTP_MODE_SERVER;
strncpy((char *)(&sntp_reply.ref_id), "X", sizeof(sntp_reply.ref_id));
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strncpy does not guarantee null termination. Use strlcpy or ensure null termination manually to prevent potential buffer overrun issues.

Suggested change
strncpy((char *)(&sntp_reply.ref_id), "X", sizeof(sntp_reply.ref_id));
strncpy((char *)(&sntp_reply.ref_id), "X", sizeof(sntp_reply.ref_id));
((char *)&sntp_reply.ref_id)[sizeof(sntp_reply.ref_id) - 1] = '\0';
Copilot uses AI. Check for mistakes.
int sntp_server_clock_source(unsigned char *refid, unsigned char stratum, char precision)
{
sntp_reply.stratum = stratum;
strncpy((char *)(&sntp_reply.ref_id), refid, sizeof(sntp_reply.ref_id));
Copy link

Copilot AI Sep 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strncpy does not guarantee null termination. Use strlcpy or ensure null termination manually to prevent potential buffer overrun issues.

Suggested change
strncpy((char *)(&sntp_reply.ref_id), refid, sizeof(sntp_reply.ref_id));
strncpy((char *)(&sntp_reply.ref_id), refid, sizeof(sntp_reply.ref_id));
((char *)&sntp_reply.ref_id)[sizeof(sntp_reply.ref_id) - 1] = '\0';
Copilot uses AI. Check for mistakes.
Copy link
Member

@jukkar jukkar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sample changes should be separated to two separate commits, one for server sample and the other for aws changes. The actual sntp server changes should also be in separate commit. So in total three commits in the PR.


LOG_INF("waiting for network");
wait_for_network();
ret = sntp_simple("ptbtime1.ptb.de", SYS_FOREVER_MS, &t);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The address of the server should be set via kconfig option. The server sample can have its own Kconfig file where the server name can be stored (see examples how to do this in other network samples). Note that the server name should be empty by default so that user is forced to set it according to his/hers network setup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6 participants