Skip to content

Commit 15a849a

Browse files
committed
mgmt: hawkbit: interface support for ip addresses and domain name
Previously, hawkbit interface only supported a url/hostname and a port, and internally it resolves to an IP address. This does not work for network layers that rely on NAT64, like OpenThread. Zephyr's implementation of `getaddrinfo` is not aware of NAT64. DNS will resolve an IPV4 address that needs to be converted to IPV6 with the NAT64 prefix. This commit alters the Hawkbit interface to allow providing an explicit domain name as a string via `server_domain`, and an already resolved IP address as `server_addr`. This commit changes the usage of `hawkbit_runtime_config.server_addr` to point to either an IP address or domain name. It adds a new Kconfig (`HAWKBIT_USE_DOMAIN_NAME`) to specify an explicit domain name and adds a new variable `hawkbit_runtime_config.server_domain`. If `HAWKBIT_USE_DOMAIN_NAME` is enabled and a user provides an IP address to `server_addr`, the user must provide a domain name to `server_domain`. Signed-off-by: Neal Jackson <[email protected]>
1 parent 36ba741 commit 15a849a

File tree

3 files changed

+108
-10
lines changed

3 files changed

+108
-10
lines changed

include/zephyr/mgmt/hawkbit/config.h

+44-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@
2929
* settings.
3030
*/
3131
struct hawkbit_runtime_config {
32-
/** Server address */
32+
/** Server address (domain name or IP address if
33+
* CONFIG_HAWKBIT_USE_DOMAIN_NAME is enabled */
3334
char *server_addr;
35+
/** Server domain name */
36+
char *server_domain;
3437
/** Server port */
3538
uint16_t server_port;
3639
/** Security token */
@@ -44,6 +47,7 @@ struct hawkbit_runtime_config {
4447
*
4548
* @param config Configuration settings to set.
4649
* @retval 0 on success.
50+
* @retval -EINVAL if string length mismatch for server_domain
4751
* @retval -EAGAIN if probe is currently running.
4852
*/
4953
int hawkbit_set_config(struct hawkbit_runtime_config *config);
@@ -55,6 +59,29 @@ int hawkbit_set_config(struct hawkbit_runtime_config *config);
5559
*/
5660
struct hawkbit_runtime_config hawkbit_get_config(void);
5761

62+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
63+
/**
64+
* @brief Set the hawkBit server hostname.
65+
*
66+
* @param hostname_str Server hostname to set.
67+
* @retval 0 on success.
68+
* @retval -EINVAL if string length mismatch for server_domain
69+
* @retval -EAGAIN if probe is currently running.
70+
*/
71+
static inline int hawkbit_set_server_domain(char *domain_str)
72+
{
73+
struct hawkbit_runtime_config set_config = {
74+
.server_addr = NULL,
75+
.server_domain = domain_str,
76+
.server_port = 0,
77+
.auth_token = NULL,
78+
.tls_tag = 0,
79+
};
80+
81+
return hawkbit_set_config(&set_config);
82+
}
83+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
84+
5885
/**
5986
* @brief Set the hawkBit server address.
6087
*
@@ -66,6 +93,7 @@ static inline int hawkbit_set_server_addr(char *addr_str)
6693
{
6794
struct hawkbit_runtime_config set_config = {
6895
.server_addr = addr_str,
96+
.server_domain = NULL,
6997
.server_port = 0,
7098
.auth_token = NULL,
7199
.tls_tag = 0,
@@ -85,6 +113,7 @@ static inline int hawkbit_set_server_port(uint16_t port)
85113
{
86114
struct hawkbit_runtime_config set_config = {
87115
.server_addr = NULL,
116+
.server_domain = NULL,
88117
.server_port = port,
89118
.auth_token = NULL,
90119
.tls_tag = 0,
@@ -104,6 +133,7 @@ static inline int hawkbit_set_ddi_security_token(char *token)
104133
{
105134
struct hawkbit_runtime_config set_config = {
106135
.server_addr = NULL,
136+
.server_domain = NULL,
107137
.server_port = 0,
108138
.auth_token = token,
109139
.tls_tag = 0,
@@ -123,6 +153,7 @@ static inline int hawkbit_set_tls_tag(sec_tag_t tag)
123153
{
124154
struct hawkbit_runtime_config set_config = {
125155
.server_addr = NULL,
156+
.server_domain = NULL,
126157
.server_port = 0,
127158
.auth_token = NULL,
128159
.tls_tag = tag,
@@ -141,6 +172,18 @@ static inline char *hawkbit_get_server_addr(void)
141172
return hawkbit_get_config().server_addr;
142173
}
143174

175+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
176+
/**
177+
* @brief Get the hawkBit server hostname.
178+
*
179+
* @return Server hostname.
180+
*/
181+
static inline char *hawkbit_get_server_domain(void)
182+
{
183+
return hawkbit_get_config().server_domain;
184+
}
185+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
186+
144187
/**
145188
* @brief Get the hawkBit server port.
146189
*

subsys/mgmt/hawkbit/Kconfig

+8
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ config HAWKBIT_SET_SETTINGS_RUNTIME
7070
help
7171
Enable to set hawkbit settings at runtime.
7272

73+
config HAWKBIT_USE_DOMAIN_NAME
74+
bool "Use server_domain for domain name instead of server_addr"
75+
depends on HAWKBIT_SET_SETTINGS_RUNTIME
76+
help
77+
Enable to use the server_domain field for TLS and HTTP. If enabled,
78+
server_addr can accept an already resolved IP address, and the domain name
79+
can be provided via server_domain.
80+
7381
choice HAWKBIT_DDI_SECURITY
7482
prompt "hawkBit DDI API authentication modes"
7583
default HAWKBIT_DDI_NO_SECURITY

subsys/mgmt/hawkbit/hawkbit.c

+56-9
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ static struct hawkbit_config {
7979
int32_t action_id;
8080
#ifdef CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME
8181
char server_addr[DNS_MAX_NAME_SIZE + 1];
82+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
83+
char server_domain[CONFIG_DNS_RESOLVER_MAX_QUERY_LEN + 1];
84+
#endif
8285
char server_port[sizeof(STRINGIFY(__UINT16_MAX__))];
8386
#ifndef CONFIG_HAWKBIT_DDI_NO_SECURITY
8487
char ddi_security_token[DDI_SECURITY_TOKEN_SIZE + 1];
@@ -90,11 +93,18 @@ static struct hawkbit_config {
9093
} hb_cfg;
9194

9295
#ifdef CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME
93-
#define HAWKBIT_SERVER hb_cfg.server_addr
96+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
97+
#define HAWKBIT_SERVER_DOMAIN hb_cfg.server_domain
98+
#define HAWKBIT_SERVER_ADDR hb_cfg.server_addr
99+
#else
100+
#define HAWKBIT_SERVER_ADDR hb_cfg.server_addr
101+
#define HAWKBIT_SERVER_DOMAIN hb_cfg.server_addr
102+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
94103
#define HAWKBIT_PORT hb_cfg.server_port
95104
#define HAWKBIT_PORT_INT atoi(hb_cfg.server_port)
96105
#else
97-
#define HAWKBIT_SERVER CONFIG_HAWKBIT_SERVER
106+
#define HAWKBIT_SERVER_ADDR CONFIG_HAWKBIT_SERVER
107+
#define HAWKBIT_SERVER_DOMAIN CONFIG_HAWKBIT_SERVER
98108
#define HAWKBIT_PORT STRINGIFY(CONFIG_HAWKBIT_PORT)
99109
#define HAWKBIT_PORT_INT CONFIG_HAWKBIT_PORT
100110
#endif /* CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME */
@@ -298,6 +308,22 @@ static int hawkbit_settings_set(const char *name, size_t len, settings_read_cb r
298308
return rc;
299309
}
300310

311+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
312+
if (settings_name_steq(name, "server_domain", &next) && !next) {
313+
if (len != sizeof(hb_cfg.server_domain)) {
314+
return -EINVAL;
315+
}
316+
317+
rc = read_cb(cb_arg, &hb_cfg.server_domain, sizeof(hb_cfg.server_domain));
318+
LOG_DBG("<%s> = %s", "hawkbit/server_domain", hb_cfg.server_domain);
319+
if (rc >= 0) {
320+
return 0;
321+
}
322+
323+
return rc;
324+
}
325+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
326+
301327
if (settings_name_steq(name, "server_port", &next) && !next) {
302328
if (len != sizeof(uint16_t)) {
303329
return -EINVAL;
@@ -336,6 +362,9 @@ static int hawkbit_settings_set(const char *name, size_t len, settings_read_cb r
336362
}
337363
#else /* CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME */
338364
if (settings_name_steq(name, "server_addr", NULL) ||
365+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
366+
settings_name_steq(name, "server_domain", NULL) ||
367+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
339368
settings_name_steq(name, "server_port", NULL) ||
340369
settings_name_steq(name, "ddi_token", NULL)) {
341370
rc = read_cb(cb_arg, NULL, 0);
@@ -359,6 +388,9 @@ static int hawkbit_settings_export(int (*cb)(const char *name, const void *value
359388
(void)cb("hawkbit/action_id", &hb_cfg.action_id, sizeof(hb_cfg.action_id));
360389
#ifdef CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME
361390
(void)cb("hawkbit/server_addr", &hb_cfg.server_addr, sizeof(hb_cfg.server_addr));
391+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
392+
(void)cb("hawkbit/server_domain", &hb_cfg.server_domain, sizeof(hb_cfg.server_domain));
393+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
362394
uint16_t hawkbit_port = atoi(hb_cfg.server_port);
363395
(void)cb("hawkbit/server_port", &hawkbit_port, sizeof(hawkbit_port));
364396
#ifndef CONFIG_HAWKBIT_DDI_NO_SECURITY
@@ -439,7 +471,7 @@ static bool start_http_client(int *hb_sock)
439471
}
440472

441473
while (resolve_attempts--) {
442-
ret = zsock_getaddrinfo(HAWKBIT_SERVER, HAWKBIT_PORT, &hints, &addr);
474+
ret = zsock_getaddrinfo(HAWKBIT_SERVER_ADDR, HAWKBIT_PORT, &hints, &addr);
443475
if (ret == 0) {
444476
break;
445477
}
@@ -469,8 +501,8 @@ static bool start_http_client(int *hb_sock)
469501
goto err_sock;
470502
}
471503

472-
if (zsock_setsockopt(*hb_sock, SOL_TLS, TLS_HOSTNAME, HAWKBIT_SERVER,
473-
sizeof(CONFIG_HAWKBIT_SERVER)) < 0) {
504+
if (zsock_setsockopt(*hb_sock, SOL_TLS, TLS_HOSTNAME, HAWKBIT_SERVER_DOMAIN,
505+
sizeof(HAWKBIT_SERVER_DOMAIN)) < 0) {
474506
goto err_sock;
475507
}
476508
#endif /* CONFIG_HAWKBIT_USE_TLS */
@@ -778,12 +810,27 @@ int hawkbit_default_config_data_cb(const char *device_id, uint8_t *buffer, const
778810
#ifdef CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME
779811
int hawkbit_set_config(struct hawkbit_runtime_config *config)
780812
{
781-
if (k_sem_take(&probe_sem, HAWKBIT_SET_SERVER_TIMEOUT) == 0) {
813+
size_t length;
814+
815+
if (k_sem_take(&probe_sem, HAWKBIT_SET_SERVER_TIMEOUT) == 0) {
782816
if (config->server_addr != NULL) {
783817
strncpy(hb_cfg.server_addr, config->server_addr,
784818
sizeof(hb_cfg.server_addr));
785819
LOG_DBG("configured %s: %s", "hawkbit/server_addr", hb_cfg.server_addr);
786820
}
821+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
822+
if (config->server_domain != NULL) {
823+
length = strnlen(config->server_domain, CONFIG_DNS_RESOLVER_MAX_QUERY_LEN + 1);
824+
if (length > CONFIG_DNS_RESOLVER_MAX_QUERY_LEN) {
825+
LOG_ERR("%s too long: %s", "hawkbit/server_domain", config->server_domain);
826+
return -EINVAL;
827+
}
828+
strncpy(hb_cfg.server_domain, config->server_domain,
829+
sizeof(hb_cfg.server_domain));
830+
LOG_DBG("configured %s: %s", "hawkbit/server_domain",
831+
hb_cfg.server_domain);
832+
}
833+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
787834
if (config->server_port != 0) {
788835
snprintf(hb_cfg.server_port, sizeof(hb_cfg.server_port), "%u",
789836
config->server_port);
@@ -817,7 +864,7 @@ int hawkbit_set_config(struct hawkbit_runtime_config *config)
817864
struct hawkbit_runtime_config hawkbit_get_config(void)
818865
{
819866
struct hawkbit_runtime_config config = {
820-
.server_addr = HAWKBIT_SERVER,
867+
.server_addr = HAWKBIT_SERVER_ADDR,
821868
.server_port = HAWKBIT_PORT_INT,
822869
.auth_token = HAWKBIT_DDI_SECURITY_TOKEN,
823870
.tls_tag = HAWKBIT_CERT_TAG,
@@ -1041,7 +1088,7 @@ static bool send_request(struct hawkbit_context *hb_context, enum hawkbit_http_r
10411088
#endif /* CONFIG_HAWKBIT_DDI_NO_SECURITY */
10421089

10431090
http_req.url = url_buffer;
1044-
http_req.host = HAWKBIT_SERVER;
1091+
http_req.host = HAWKBIT_SERVER_DOMAIN;
10451092
http_req.port = HAWKBIT_PORT;
10461093
http_req.protocol = "HTTP/1.1";
10471094
http_req.response = response_cb;
@@ -1155,7 +1202,7 @@ void hawkbit_reboot(void)
11551202

11561203
static bool check_hawkbit_server(void)
11571204
{
1158-
if (strlen(HAWKBIT_SERVER) == 0) {
1205+
if (strlen(HAWKBIT_SERVER_ADDR) == 0) {
11591206
if (sizeof(CONFIG_HAWKBIT_SERVER) > 1) {
11601207
hawkbit_set_server_addr(CONFIG_HAWKBIT_SERVER);
11611208
} else {

0 commit comments

Comments
 (0)