Remove network specific default and max log level setting and start to use the zephyr logging values for those. Remove LOG_MODULE_REGISTER() from net_core.h and place the calls into .c files. This is done in order to avoid weird compiler errors in some cases and to make the code look similar as other subsystems. Fixes #11343 Fixes #11659 Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
226 lines
4.7 KiB
C
226 lines
4.7 KiB
C
/*
|
|
* Copyright (c) 2017 Linaro Limited
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/* libc headers */
|
|
#include <stdlib.h>
|
|
|
|
/* Zephyr headers */
|
|
#include <logging/log.h>
|
|
LOG_MODULE_REGISTER(net_sock_addr, CONFIG_NET_SOCKETS_LOG_LEVEL);
|
|
|
|
#include <kernel.h>
|
|
#include <net/socket.h>
|
|
#include <syscall_handler.h>
|
|
|
|
#define AI_ARR_MAX 2
|
|
|
|
#if defined(CONFIG_DNS_RESOLVER)
|
|
|
|
struct getaddrinfo_state {
|
|
const struct zsock_addrinfo *hints;
|
|
struct k_sem sem;
|
|
int status;
|
|
u16_t idx;
|
|
u16_t port;
|
|
struct zsock_addrinfo *ai_arr;
|
|
};
|
|
|
|
static void dns_resolve_cb(enum dns_resolve_status status,
|
|
struct dns_addrinfo *info, void *user_data)
|
|
{
|
|
struct getaddrinfo_state *state = user_data;
|
|
struct zsock_addrinfo *ai;
|
|
int socktype = SOCK_STREAM;
|
|
int proto;
|
|
|
|
NET_DBG("dns status: %d", status);
|
|
|
|
if (info == NULL) {
|
|
if (status == DNS_EAI_ALLDONE) {
|
|
status = 0;
|
|
}
|
|
state->status = status;
|
|
k_sem_give(&state->sem);
|
|
return;
|
|
}
|
|
|
|
if (state->idx >= AI_ARR_MAX) {
|
|
NET_DBG("getaddrinfo entries overflow");
|
|
return;
|
|
}
|
|
|
|
ai = &state->ai_arr[state->idx];
|
|
memcpy(&ai->_ai_addr, &info->ai_addr, info->ai_addrlen);
|
|
net_sin(&ai->_ai_addr)->sin_port = state->port;
|
|
ai->ai_addr = &ai->_ai_addr;
|
|
ai->ai_addrlen = info->ai_addrlen;
|
|
memcpy(&ai->_ai_canonname, &info->ai_canonname,
|
|
sizeof(ai->_ai_canonname));
|
|
ai->ai_canonname = ai->_ai_canonname;
|
|
ai->ai_family = info->ai_family;
|
|
|
|
if (state->hints) {
|
|
if (state->hints->ai_socktype) {
|
|
socktype = state->hints->ai_socktype;
|
|
}
|
|
}
|
|
|
|
proto = IPPROTO_TCP;
|
|
if (socktype == SOCK_DGRAM) {
|
|
proto = IPPROTO_UDP;
|
|
}
|
|
|
|
ai->ai_socktype = socktype;
|
|
ai->ai_protocol = proto;
|
|
|
|
state->idx++;
|
|
}
|
|
|
|
|
|
int _impl_z_zsock_getaddrinfo_internal(const char *host, const char *service,
|
|
const struct zsock_addrinfo *hints,
|
|
struct zsock_addrinfo *res)
|
|
{
|
|
int family = AF_UNSPEC;
|
|
long int port = 0;
|
|
int st1 = DNS_EAI_ADDRFAMILY, st2 = DNS_EAI_ADDRFAMILY;
|
|
struct sockaddr *ai_addr;
|
|
int ret;
|
|
struct getaddrinfo_state ai_state;
|
|
|
|
if (hints) {
|
|
family = hints->ai_family;
|
|
}
|
|
|
|
if (service) {
|
|
port = strtol(service, NULL, 10);
|
|
if (port < 1 || port > 65535) {
|
|
return DNS_EAI_NONAME;
|
|
}
|
|
}
|
|
|
|
ai_state.hints = hints;
|
|
ai_state.idx = 0U;
|
|
ai_state.port = htons(port);
|
|
ai_state.ai_arr = res;
|
|
k_sem_init(&ai_state.sem, 0, UINT_MAX);
|
|
|
|
/* Link entries in advance */
|
|
ai_state.ai_arr[0].ai_next = &ai_state.ai_arr[1];
|
|
|
|
/* Execute if AF_UNSPEC or AF_INET4 */
|
|
if (family != AF_INET6) {
|
|
ret = dns_get_addr_info(host, DNS_QUERY_TYPE_A, NULL,
|
|
dns_resolve_cb, &ai_state, 1000);
|
|
if (ret == 0) {
|
|
k_sem_take(&ai_state.sem, K_FOREVER);
|
|
st1 = ai_state.status;
|
|
} else {
|
|
errno = -ret;
|
|
st1 = DNS_EAI_SYSTEM;
|
|
}
|
|
|
|
if (ai_state.idx > 0) {
|
|
ai_addr = &ai_state.ai_arr[ai_state.idx - 1]._ai_addr;
|
|
net_sin(ai_addr)->sin_port = htons(port);
|
|
}
|
|
}
|
|
|
|
#if defined(CONFIG_NET_IPV6)
|
|
/* Execute if AF_UNSPEC or AF_INET6 */
|
|
if (family != AF_INET) {
|
|
ret = dns_get_addr_info(host, DNS_QUERY_TYPE_AAAA, NULL,
|
|
dns_resolve_cb, &ai_state, 1000);
|
|
if (ret == 0) {
|
|
k_sem_take(&ai_state.sem, K_FOREVER);
|
|
st2 = ai_state.status;
|
|
} else {
|
|
errno = -ret;
|
|
st2 = DNS_EAI_SYSTEM;
|
|
}
|
|
|
|
if (ai_state.idx > 0) {
|
|
ai_addr = &ai_state.ai_arr[ai_state.idx - 1]._ai_addr;
|
|
net_sin6(ai_addr)->sin6_port = htons(port);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* If both attempts failed, it's error */
|
|
if (st1 && st2) {
|
|
if (st1 != DNS_EAI_ADDRFAMILY) {
|
|
return st1;
|
|
}
|
|
return st2;
|
|
}
|
|
|
|
/* Mark entry as last */
|
|
ai_state.ai_arr[ai_state.idx - 1].ai_next = NULL;
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_USERSPACE
|
|
Z_SYSCALL_HANDLER(z_zsock_getaddrinfo_internal, host, service, hints, res)
|
|
{
|
|
struct zsock_addrinfo hints_copy;
|
|
char *host_copy = NULL, *service_copy = NULL;
|
|
u32_t ret;
|
|
|
|
if (hints) {
|
|
Z_OOPS(z_user_from_copy(&hints_copy, (void *)hints,
|
|
sizeof(hints_copy)));
|
|
}
|
|
Z_OOPS(Z_SYSCALL_MEMORY_ARRAY_WRITE(res, AI_ARR_MAX,
|
|
sizeof(struct zsock_addrinfo)));
|
|
|
|
if (service) {
|
|
service_copy = z_user_string_alloc_copy((char *)service, 64);
|
|
if (!service_copy) {
|
|
ret = DNS_EAI_MEMORY;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
if (host) {
|
|
host_copy = z_user_string_alloc_copy((char *)host, 64);
|
|
if (!host_copy) {
|
|
ret = DNS_EAI_MEMORY;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
ret = _impl_z_zsock_getaddrinfo_internal(host_copy, service_copy,
|
|
hints ? &hints_copy : NULL,
|
|
(struct zsock_addrinfo *)res);
|
|
out:
|
|
k_free(service_copy);
|
|
k_free(host_copy);
|
|
|
|
return ret;
|
|
}
|
|
#endif /* CONFIG_USERSPACE */
|
|
|
|
int zsock_getaddrinfo(const char *host, const char *service,
|
|
const struct zsock_addrinfo *hints,
|
|
struct zsock_addrinfo **res)
|
|
{
|
|
int ret;
|
|
|
|
*res = calloc(AI_ARR_MAX, sizeof(struct zsock_addrinfo));
|
|
if (!(*res)) {
|
|
return DNS_EAI_MEMORY;
|
|
}
|
|
ret = z_zsock_getaddrinfo_internal(host, service, hints, *res);
|
|
if (ret) {
|
|
free(*res);
|
|
*res = NULL;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#endif
|