Skip to content

Commit 5512401

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 b915e24 commit 5512401

File tree

3 files changed

+112
-9
lines changed

3 files changed

+112
-9
lines changed

include/zephyr/mgmt/hawkbit/config.h

+42-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@
2929
* settings.
3030
*/
3131
struct hawkbit_runtime_config {
32-
/** Server address */
32+
/**
33+
* Server address (domain name or IP address if
34+
* CONFIG_HAWKBIT_USE_DOMAIN_NAME is enabled
35+
*/
3336
char *server_addr;
37+
/** Server domain name */
38+
char *server_domain;
3439
/** Server port */
3540
uint16_t server_port;
3641
/** Security token */
@@ -44,6 +49,7 @@ struct hawkbit_runtime_config {
4449
*
4550
* @param config Configuration settings to set.
4651
* @retval 0 on success.
52+
* @retval -EINVAL if string length mismatch for server_domain
4753
* @retval -EAGAIN if probe is currently running.
4854
*/
4955
int hawkbit_set_config(struct hawkbit_runtime_config *config);
@@ -55,6 +61,27 @@ int hawkbit_set_config(struct hawkbit_runtime_config *config);
5561
*/
5662
struct hawkbit_runtime_config hawkbit_get_config(void);
5763

64+
/**
65+
* @brief Set the hawkBit server hostname.
66+
*
67+
* @param hostname_str Server hostname to set.
68+
* @retval 0 on success.
69+
* @retval -EINVAL if string length mismatch for server_domain
70+
* @retval -EAGAIN if probe is currently running.
71+
*/
72+
static inline int hawkbit_set_server_domain(char *domain_str)
73+
{
74+
struct hawkbit_runtime_config set_config = {
75+
.server_addr = NULL,
76+
.server_domain = domain_str,
77+
.server_port = 0,
78+
.auth_token = NULL,
79+
.tls_tag = 0,
80+
};
81+
82+
return hawkbit_set_config(&set_config);
83+
}
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,16 @@ static inline char *hawkbit_get_server_addr(void)
141172
return hawkbit_get_config().server_addr;
142173
}
143174

175+
/**
176+
* @brief Get the hawkBit server hostname.
177+
*
178+
* @return Server hostname.
179+
*/
180+
static inline char *hawkbit_get_server_domain(void)
181+
{
182+
return hawkbit_get_config().server_domain;
183+
}
184+
144185
/**
145186
* @brief Get the hawkBit server port.
146187
*

subsys/mgmt/hawkbit/Kconfig

+16
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,22 @@ 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+
81+
config HAWKBIT_DOMAIN_NAME_MAX_LEN
82+
int "The buffer size for storing the domain name string"
83+
default DNS_RESOLVER_MAX_QUERY_LEN if DNS_RESOLVER
84+
default 255
85+
depends on HAWKBIT_USE_DOMAIN_NAME
86+
help
87+
The size for the internal buffer used to hold the domain name string.
88+
7389
choice HAWKBIT_DDI_SECURITY
7490
prompt "hawkBit DDI API authentication modes"
7591
default HAWKBIT_DDI_NO_SECURITY

subsys/mgmt/hawkbit/hawkbit.c

+54-8
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_HAWKBIT_DOMAIN_NAME_MAX_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,17 @@ 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+
#else
99+
#define HAWKBIT_SERVER_DOMAIN hb_cfg.server_addr
100+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
101+
#define HAWKBIT_SERVER_ADDR hb_cfg.server_addr
94102
#define HAWKBIT_PORT hb_cfg.server_port
95103
#define HAWKBIT_PORT_INT atoi(hb_cfg.server_port)
96104
#else
97-
#define HAWKBIT_SERVER CONFIG_HAWKBIT_SERVER
105+
#define HAWKBIT_SERVER_ADDR CONFIG_HAWKBIT_SERVER
106+
#define HAWKBIT_SERVER_DOMAIN CONFIG_HAWKBIT_SERVER
98107
#define HAWKBIT_PORT STRINGIFY(CONFIG_HAWKBIT_PORT)
99108
#define HAWKBIT_PORT_INT CONFIG_HAWKBIT_PORT
100109
#endif /* CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME */
@@ -298,6 +307,22 @@ static int hawkbit_settings_set(const char *name, size_t len, settings_read_cb r
298307
return rc;
299308
}
300309

310+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
311+
if (settings_name_steq(name, "server_domain", &next) && !next) {
312+
if (len != sizeof(hb_cfg.server_domain)) {
313+
return -EINVAL;
314+
}
315+
316+
rc = read_cb(cb_arg, &hb_cfg.server_domain, sizeof(hb_cfg.server_domain));
317+
LOG_DBG("<%s> = %s", "hawkbit/server_domain", hb_cfg.server_domain);
318+
if (rc >= 0) {
319+
return 0;
320+
}
321+
322+
return rc;
323+
}
324+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
325+
301326
if (settings_name_steq(name, "server_port", &next) && !next) {
302327
if (len != sizeof(uint16_t)) {
303328
return -EINVAL;
@@ -336,6 +361,9 @@ static int hawkbit_settings_set(const char *name, size_t len, settings_read_cb r
336361
}
337362
#else /* CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME */
338363
if (settings_name_steq(name, "server_addr", NULL) ||
364+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
365+
settings_name_steq(name, "server_domain", NULL) ||
366+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
339367
settings_name_steq(name, "server_port", NULL) ||
340368
settings_name_steq(name, "ddi_token", NULL)) {
341369
rc = read_cb(cb_arg, NULL, 0);
@@ -359,6 +387,9 @@ static int hawkbit_settings_export(int (*cb)(const char *name, const void *value
359387
(void)cb("hawkbit/action_id", &hb_cfg.action_id, sizeof(hb_cfg.action_id));
360388
#ifdef CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME
361389
(void)cb("hawkbit/server_addr", &hb_cfg.server_addr, sizeof(hb_cfg.server_addr));
390+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
391+
(void)cb("hawkbit/server_domain", &hb_cfg.server_domain, sizeof(hb_cfg.server_domain));
392+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
362393
uint16_t hawkbit_port = atoi(hb_cfg.server_port);
363394
(void)cb("hawkbit/server_port", &hawkbit_port, sizeof(hawkbit_port));
364395
#ifndef CONFIG_HAWKBIT_DDI_NO_SECURITY
@@ -439,7 +470,7 @@ static bool start_http_client(int *hb_sock)
439470
}
440471

441472
while (resolve_attempts--) {
442-
ret = zsock_getaddrinfo(HAWKBIT_SERVER, HAWKBIT_PORT, &hints, &addr);
473+
ret = zsock_getaddrinfo(HAWKBIT_SERVER_ADDR, HAWKBIT_PORT, &hints, &addr);
443474
if (ret == 0) {
444475
break;
445476
}
@@ -469,8 +500,8 @@ static bool start_http_client(int *hb_sock)
469500
goto err_sock;
470501
}
471502

472-
if (zsock_setsockopt(*hb_sock, SOL_TLS, TLS_HOSTNAME, HAWKBIT_SERVER,
473-
sizeof(CONFIG_HAWKBIT_SERVER)) < 0) {
503+
if (zsock_setsockopt(*hb_sock, SOL_TLS, TLS_HOSTNAME, HAWKBIT_SERVER_DOMAIN,
504+
sizeof(HAWKBIT_SERVER_DOMAIN)) < 0) {
474505
goto err_sock;
475506
}
476507
#endif /* CONFIG_HAWKBIT_USE_TLS */
@@ -778,12 +809,27 @@ int hawkbit_default_config_data_cb(const char *device_id, uint8_t *buffer, const
778809
#ifdef CONFIG_HAWKBIT_SET_SETTINGS_RUNTIME
779810
int hawkbit_set_config(struct hawkbit_runtime_config *config)
780811
{
812+
size_t length;
813+
781814
if (k_sem_take(&probe_sem, HAWKBIT_SET_SERVER_TIMEOUT) == 0) {
782815
if (config->server_addr != NULL) {
783816
strncpy(hb_cfg.server_addr, config->server_addr,
784817
sizeof(hb_cfg.server_addr));
785818
LOG_DBG("configured %s: %s", "hawkbit/server_addr", hb_cfg.server_addr);
786819
}
820+
#ifdef CONFIG_HAWKBIT_USE_DOMAIN_NAME
821+
if (config->server_domain != NULL) {
822+
length = strnlen(config->server_domain, CONFIG_DNS_RESOLVER_MAX_QUERY_LEN + 1);
823+
if (length > CONFIG_DNS_RESOLVER_MAX_QUERY_LEN) {
824+
LOG_ERR("%s too long: %s", "hawkbit/server_domain", config->server_domain);
825+
return -EINVAL;
826+
}
827+
strncpy(hb_cfg.server_domain, config->server_domain,
828+
sizeof(hb_cfg.server_domain));
829+
LOG_DBG("configured %s: %s", "hawkbit/server_domain",
830+
hb_cfg.server_domain);
831+
}
832+
#endif /* CONFIG_HAWKBIT_USE_DOMAIN_NAME */
787833
if (config->server_port != 0) {
788834
snprintf(hb_cfg.server_port, sizeof(hb_cfg.server_port), "%u",
789835
config->server_port);
@@ -817,7 +863,7 @@ int hawkbit_set_config(struct hawkbit_runtime_config *config)
817863
struct hawkbit_runtime_config hawkbit_get_config(void)
818864
{
819865
struct hawkbit_runtime_config config = {
820-
.server_addr = HAWKBIT_SERVER,
866+
.server_addr = HAWKBIT_SERVER_ADDR,
821867
.server_port = HAWKBIT_PORT_INT,
822868
.auth_token = HAWKBIT_DDI_SECURITY_TOKEN,
823869
.tls_tag = HAWKBIT_CERT_TAG,
@@ -1041,7 +1087,7 @@ static bool send_request(struct hawkbit_context *hb_context, enum hawkbit_http_r
10411087
#endif /* CONFIG_HAWKBIT_DDI_NO_SECURITY */
10421088

10431089
http_req.url = url_buffer;
1044-
http_req.host = HAWKBIT_SERVER;
1090+
http_req.host = HAWKBIT_SERVER_DOMAIN;
10451091
http_req.port = HAWKBIT_PORT;
10461092
http_req.protocol = "HTTP/1.1";
10471093
http_req.response = response_cb;
@@ -1155,7 +1201,7 @@ void hawkbit_reboot(void)
11551201

11561202
static bool check_hawkbit_server(void)
11571203
{
1158-
if (strlen(HAWKBIT_SERVER) == 0) {
1204+
if (strlen(HAWKBIT_SERVER_ADDR) == 0) {
11591205
if (sizeof(CONFIG_HAWKBIT_SERVER) > 1) {
11601206
hawkbit_set_server_addr(CONFIG_HAWKBIT_SERVER);
11611207
} else {

0 commit comments

Comments
 (0)