diff --git a/net/golioth/CMakeLists.txt b/net/golioth/CMakeLists.txt index 6ad0c372..6253c102 100644 --- a/net/golioth/CMakeLists.txt +++ b/net/golioth/CMakeLists.txt @@ -11,6 +11,7 @@ zephyr_library_sources_ifdef(CONFIG_GOLIOTH_RPC rpc.c) zephyr_library_sources_ifdef(CONFIG_GOLIOTH_SETTINGS settings.c) zephyr_library_sources_ifdef(CONFIG_GOLIOTH_SYSTEM_CLIENT system_client.c) zephyr_library_sources_ifdef(CONFIG_ZCBOR zcbor_utils.c) +zephyr_library_sources_ifdef(CONFIG_NET_L2_OPENTHREAD ot_dns.c) if(CONFIG_GOLIOTH_AUTH_METHOD_CERT) set(path ${CONFIG_GOLIOTH_SYSTEM_CLIENT_CA_PATH}) diff --git a/net/golioth/ot_dns.c b/net/golioth/ot_dns.c new file mode 100644 index 00000000..6cf0ee0d --- /dev/null +++ b/net/golioth/ot_dns.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 Golioth, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(golioth_openthread, CONFIG_GOLIOTH_SYSTEM_CLIENT_LOG_LEVEL); + +#include +#include +#include +#include + +static otDnsQueryConfig dns_query; +static char *golioth_ip6_addr; + +K_SEM_DEFINE(ot_dns_resolve, 0, 1); + +/* Callback for NAT64 IPv6 translated Golioth System Server address from the DNS query response */ +static void ot_dns_callback(otError aError, const otDnsAddressResponse *aResponse, void *aContext) +{ + otIp6Address golioth_addr; + + if (aError != OT_ERROR_NONE) { + LOG_ERR("Golioth System Server DNS resolving error: %d", aError); + return; + } + + if (otDnsAddressResponseGetAddress(aResponse, 0, &golioth_addr, NULL) == OT_ERROR_NONE) { + otIp6AddressToString(&golioth_addr, + golioth_ip6_addr, + OT_IP6_ADDRESS_STRING_SIZE); + } + + k_sem_give(&ot_dns_resolve); +} + +int synthesize_ip6_address(char *hostname, char *ip6_addr_buffer) +{ + int err = 0; + golioth_ip6_addr = ip6_addr_buffer; + + struct openthread_context *ot_context = openthread_get_default_context(); + + otIp4Address dns_server_addr; + + err = otIp4AddressFromString(CONFIG_DNS_SERVER1, &dns_server_addr); + if (err != OT_ERROR_NONE) { + LOG_ERR("DNS server IPv4 address error: %d", err); + return err; + } + + err = otNat64SynthesizeIp6Address(ot_context->instance, + &dns_server_addr, + &dns_query.mServerSockAddr.mAddress); + if (err != OT_ERROR_NONE) { + LOG_ERR("Synthesize DNS server IPv6 address error: %d", err); + return err; + } + + err = otDnsClientResolveIp4Address(ot_context->instance, + hostname, + ot_dns_callback, + ot_context, + &dns_query); + if (err != OT_ERROR_NONE) { + LOG_ERR("Golioth System Server address resolution DNS query error: %d", err); + return err; + } + + k_sem_take(&ot_dns_resolve, K_FOREVER); + + return 0; +} + diff --git a/net/golioth/ot_dns.h b/net/golioth/ot_dns.h new file mode 100644 index 00000000..03db3bbc --- /dev/null +++ b/net/golioth/ot_dns.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 Golioth, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __OT_DNS_H__ +#define __OT_DNS_H__ + +/** + * @brief Synthesize the IPv6 address from a given host name + * + * Get the IPv6 address of Golioth Server to avoid hardcoding it in applications. + * NAT64 prefix used by the Thread Border Router is set while synthesizing the address. + * + * @param[in] hostname A pointer to the host name for which to querry the address + * @param[out] ip6_addr_buffer A buffer to char array to output the synthesized IPv6 address + * + * @retval 0 On success + * @retval <0 On failure + */ +int synthesize_ip6_address(char *hostname, char *ip6_addr_buffer); + +#endif /* __OT_DNS_GOL_H__ */ diff --git a/net/golioth/system_client.c b/net/golioth/system_client.c index 13c6cb24..e56f4441 100644 --- a/net/golioth/system_client.c +++ b/net/golioth/system_client.c @@ -17,8 +17,12 @@ LOG_MODULE_REGISTER(golioth_system, CONFIG_GOLIOTH_SYSTEM_CLIENT_LOG_LEVEL); #include #include +#include "ot_dns.h" + #define RX_BUFFER_SIZE CONFIG_GOLIOTH_SYSTEM_CLIENT_RX_BUF_SIZE +static char golioth_system_server_host[40] = CONFIG_GOLIOTH_SYSTEM_SERVER_HOST; + static const uint8_t tls_ca_crt[] = { #if defined(CONFIG_GOLIOTH_SYSTEM_CLIENT_CA_PATH) #include "golioth-systemclient-ca.inc" @@ -244,11 +248,22 @@ SYS_INIT(golioth_system_init, APPLICATION, static int client_connect(struct golioth_client *client) { - int err; + int err = 0; + +#if defined(CONFIG_NET_L2_OPENTHREAD) + + err = synthesize_ip6_address(golioth_system_server_host, golioth_system_server_host); + if (err) { + LOG_ERR("Failed to synthesize Golioth Server IPv6 address: %d", err); + return err; + } + +#endif err = golioth_connect(client, - CONFIG_GOLIOTH_SYSTEM_SERVER_HOST, + golioth_system_server_host, CONFIG_GOLIOTH_SYSTEM_SERVER_PORT); + if (err) { LOG_ERR("Failed to connect: %d", err); return err;