zephyr/subsys/net/lib/app/server.c
Jukka Rissanen 86689030e8 net: Clarify logging in networking code
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>
2018-12-07 12:00:04 +02:00

517 lines
11 KiB
C

/* server.c */
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <logging/log.h>
LOG_MODULE_DECLARE(net_app, CONFIG_NET_APP_LOG_LEVEL);
#include <zephyr.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <net/net_core.h>
#include <net/net_ip.h>
#include <net/net_if.h>
#include <net/net_app.h>
#include "net_app_private.h"
#if defined(CONFIG_NET_TCP)
static void new_client(struct net_context *net_ctx,
const struct sockaddr *addr)
{
#if CONFIG_NET_APP_LOG_LEVEL >= LOG_LEVEL_WRN
#if defined(CONFIG_NET_IPV6)
#define PORT_STR sizeof("[]:xxxxx")
char buf[NET_IPV6_ADDR_LEN + PORT_STR];
#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
#define PORT_STR sizeof(":xxxxx")
char buf[NET_IPV4_ADDR_LEN + PORT_STR];
#endif
NET_INFO("Connection from %s (%p)",
log_strdup(_net_app_sprint_ipaddr(buf, sizeof(buf), addr)),
net_ctx);
#endif
}
static int get_avail_net_ctx(struct net_app_ctx *ctx)
{
int i;
for (i = 0; i < CONFIG_NET_APP_SERVER_NUM_CONN; i++) {
if (!ctx->server.net_ctxs[i] ||
!net_context_is_used(ctx->server.net_ctxs[i])) {
return i;
}
}
return -1;
}
void _net_app_accept_cb(struct net_context *net_ctx,
struct sockaddr *addr,
socklen_t addrlen,
int status, void *data)
{
struct net_app_ctx *ctx = data;
int i, ret;
ARG_UNUSED(addr);
ARG_UNUSED(addrlen);
i = get_avail_net_ctx(ctx);
if (i < 0 || status != 0 || !ctx->is_enabled) {
/* We are already connected and there are no free context slots
* available so this new connection must be closed.
*/
net_context_put(net_ctx);
if (ctx->cb.connect) {
if (!status) {
status = -ECONNREFUSED;
}
ctx->cb.connect(ctx, status, ctx->user_data);
}
if (i < 0) {
NET_DBG("All connection slots occupied, new "
"connection dropped");
}
return;
}
NET_DBG("[%d] Accepted net_ctx %p", i, net_ctx);
ret = net_context_recv(net_ctx, ctx->recv_cb, K_NO_WAIT, ctx);
if (ret < 0) {
NET_DBG("Cannot set recv_cb (%d)", ret);
}
ctx->server.net_ctxs[i] = net_ctx;
/* We need to set the backpointer here, as otherwise it is impossible
* to find the correct net_ctx from a list of net_ctxs.
*/
net_ctx->net_app = ctx;
new_client(net_ctx, addr);
if (ctx->cb.connect) {
ctx->cb.connect(ctx, 0, ctx->user_data);
}
}
#endif /* CONFIG_NET_TCP */
int net_app_listen(struct net_app_ctx *ctx)
{
bool dual = false, v4_failed = false;
int ret;
if (!ctx) {
return -EINVAL;
}
if (!ctx->is_init) {
return -ENOENT;
}
if (ctx->app_type != NET_APP_SERVER) {
return -EINVAL;
}
#if defined(CONFIG_NET_IPV4)
if (ctx->ipv4.local.sa_family == AF_UNSPEC) {
ctx->ipv4.local.sa_family = AF_INET;
dual = true;
_net_app_set_local_addr(ctx, &ctx->ipv4.local, NULL,
net_sin(&ctx->ipv4.local)->sin_port);
}
ret = _net_app_set_net_ctx(ctx, ctx->ipv4.ctx, &ctx->ipv4.local,
sizeof(struct sockaddr_in), ctx->proto);
if (ret < 0) {
if (ctx->ipv4.ctx) {
net_context_put(ctx->ipv4.ctx);
ctx->ipv4.ctx = NULL;
}
v4_failed = true;
}
#if defined(CONFIG_NET_APP_DTLS)
else {
if (ctx->is_tls && ctx->proto == IPPROTO_UDP) {
net_context_recv(ctx->ipv4.ctx, ctx->recv_cb,
K_NO_WAIT, ctx);
}
}
#endif
#endif /* CONFIG_NET_IPV4 */
/* We ignore the IPv4 error if IPv6 is enabled */
#if defined(CONFIG_NET_IPV6)
if (ctx->ipv6.local.sa_family == AF_UNSPEC || dual) {
ctx->ipv6.local.sa_family = AF_INET6;
_net_app_set_local_addr(ctx, &ctx->ipv6.local, NULL,
net_sin6(&ctx->ipv6.local)->sin6_port);
}
ret = _net_app_set_net_ctx(ctx, ctx->ipv6.ctx, &ctx->ipv6.local,
sizeof(struct sockaddr_in6), ctx->proto);
if (ret < 0) {
if (ctx->ipv6.ctx) {
net_context_put(ctx->ipv6.ctx);
ctx->ipv6.ctx = NULL;
}
if (!v4_failed) {
ret = 0;
}
}
#if defined(CONFIG_NET_APP_DTLS)
else {
if (ctx->is_tls && ctx->proto == IPPROTO_UDP) {
net_context_recv(ctx->ipv6.ctx, ctx->recv_cb,
K_NO_WAIT, ctx);
}
}
#endif
#endif /* CONFIG_NET_IPV6 */
return ret;
}
int net_app_init_server(struct net_app_ctx *ctx,
enum net_sock_type sock_type,
enum net_ip_protocol proto,
struct sockaddr *server_addr,
u16_t port,
void *user_data)
{
int ret;
if (!ctx) {
return -EINVAL;
}
if (ctx->is_init) {
return -EALREADY;
}
#if defined(CONFIG_NET_IPV4)
(void)memset(&ctx->ipv4.local, 0, sizeof(ctx->ipv4.local));
ctx->ipv4.local.sa_family = AF_INET;
#endif
#if defined(CONFIG_NET_IPV6)
(void)memset(&ctx->ipv6.local, 0, sizeof(ctx->ipv6.local));
ctx->ipv6.local.sa_family = AF_INET6;
#endif
if (server_addr) {
if (server_addr->sa_family == AF_INET) {
#if defined(CONFIG_NET_IPV4)
memcpy(&ctx->ipv4.local, server_addr,
sizeof(ctx->ipv4.local));
#else
return -EPROTONOSUPPORT;
#endif
}
if (server_addr->sa_family == AF_INET6) {
#if defined(CONFIG_NET_IPV6)
memcpy(&ctx->ipv6.local, server_addr,
sizeof(ctx->ipv6.local));
#else
return -EPROTONOSUPPORT;
#endif
}
if (server_addr->sa_family == AF_UNSPEC) {
#if defined(CONFIG_NET_IPV4)
net_sin(&ctx->ipv4.local)->sin_port =
net_sin(server_addr)->sin_port;
#endif
#if defined(CONFIG_NET_IPV6)
net_sin6(&ctx->ipv6.local)->sin6_port =
net_sin6(server_addr)->sin6_port;
#endif
}
} else {
if (port == 0) {
return -EINVAL;
}
#if defined(CONFIG_NET_IPV4)
net_sin(&ctx->ipv4.local)->sin_port = htons(port);
#endif
#if defined(CONFIG_NET_IPV6)
net_sin6(&ctx->ipv6.local)->sin6_port = htons(port);
#endif
}
ctx->app_type = NET_APP_SERVER;
ctx->user_data = user_data;
ctx->send_data = net_context_sendto;
ctx->recv_cb = _net_app_received;
ctx->proto = proto;
ctx->sock_type = sock_type;
ret = _net_app_config_local_ctx(ctx, sock_type, proto, server_addr);
if (ret < 0) {
goto fail;
}
NET_ASSERT_INFO(ctx->default_ctx, "Default ctx not selected");
ctx->is_init = true;
_net_app_register(ctx);
fail:
return ret;
}
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
static inline void new_server(struct net_app_ctx *ctx,
const char *server_banner)
{
#if CONFIG_NET_APP_LOG_LEVEL >= LOG_LEVEL_WRN
#if defined(CONFIG_NET_IPV6)
#define PORT_STR sizeof("[]:xxxxx")
char buf[NET_IPV6_ADDR_LEN + PORT_STR];
#elif defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
#define PORT_STR sizeof(":xxxxx")
char buf[NET_IPV4_ADDR_LEN + PORT_STR];
#endif
#if defined(CONFIG_NET_IPV6)
NET_INFO("%s %s (%p)", log_strdup(server_banner),
log_strdup(_net_app_sprint_ipaddr(buf, sizeof(buf),
&ctx->ipv6.local)),
ctx);
#endif
#if defined(CONFIG_NET_IPV4)
NET_INFO("%s %s (%p)", log_strdup(server_banner),
log_strdup(_net_app_sprint_ipaddr(buf, sizeof(buf),
&ctx->ipv4.local)),
ctx);
#endif
#endif
}
static struct net_context *find_net_ctx(struct net_app_ctx *ctx,
int *idx)
{
int i;
for (i = 0; i < CONFIG_NET_APP_SERVER_NUM_CONN; i++) {
if (ctx->server.net_ctxs[i] &&
ctx->server.net_ctxs[i]->net_app == ctx &&
net_context_is_used(ctx->server.net_ctxs[i])) {
*idx = i;
return ctx->server.net_ctxs[i];
}
}
return NULL;
}
static void tls_server_handler(struct net_app_ctx *ctx,
struct k_sem *startup_sync)
{
int ret, i;
NET_DBG("Starting TLS server thread for %p", ctx);
ret = _net_app_tls_init(ctx, MBEDTLS_SSL_IS_SERVER);
if (ret < 0) {
NET_DBG("TLS server init failed");
return;
}
k_sem_give(startup_sync);
while (1) {
struct net_context *net_ctx;
_net_app_ssl_mainloop(ctx);
NET_DBG("Closing %p connection", ctx);
ctx->tls.close_requested = false;
mbedtls_ssl_close_notify(&ctx->tls.mbedtls.ssl);
ctx->tls.tx_pending = false;
if (ctx->cb.close) {
ctx->cb.close(ctx, -ESHUTDOWN, ctx->user_data);
}
net_ctx = find_net_ctx(ctx, &i);
if (net_ctx) {
NET_DBG("Server context %p removed", net_ctx);
net_context_put(net_ctx);
ctx->server.net_ctxs[i] = NULL;
}
}
}
#define TLS_STARTUP_TIMEOUT K_SECONDS(5)
bool _net_app_server_tls_enable(struct net_app_ctx *ctx)
{
struct k_sem startup_sync;
NET_ASSERT(ctx);
if (!(ctx->tls.stack && ctx->tls.stack_size > 0)) {
/* No stack or stack size is 0, we cannot enable */
return false;
}
/* Start the thread that handles TLS traffic. */
if (!ctx->tls.tid) {
k_sem_init(&startup_sync, 0, 1);
ctx->tls.tid = k_thread_create(&ctx->tls.thread,
ctx->tls.stack,
ctx->tls.stack_size,
(k_thread_entry_t)
tls_server_handler,
ctx, &startup_sync, 0,
K_PRIO_COOP(7), 0, 0);
/* Wait until we know that the TLS thread startup was ok */
if (k_sem_take(&startup_sync, TLS_STARTUP_TIMEOUT) < 0) {
NET_ERR("TLS server handler start failed");
_net_app_tls_handler_stop(ctx);
return false;
}
}
return true;
}
bool _net_app_server_tls_disable(struct net_app_ctx *ctx)
{
NET_ASSERT(ctx);
if (!ctx->tls.tid) {
return false;
}
_net_app_tls_handler_stop(ctx);
return true;
}
int net_app_server_tls(struct net_app_ctx *ctx,
u8_t *request_buf,
size_t request_buf_len,
const char *server_banner,
u8_t *personalization_data,
size_t personalization_data_len,
net_app_cert_cb_t cert_cb,
net_app_entropy_src_cb_t entropy_src_cb,
struct k_mem_pool *pool,
k_thread_stack_t *stack,
size_t stack_size)
{
if (!request_buf || request_buf_len == 0) {
NET_ERR("Request buf must be set");
return -EINVAL;
}
/* mbedtls cannot receive or send larger buffer as what is defined
* in a file pointed by CONFIG_MBEDTLS_CFG_FILE.
*/
if (request_buf_len > MBEDTLS_SSL_MAX_CONTENT_LEN) {
NET_ERR("Request buf too large, max len is %d",
MBEDTLS_SSL_MAX_CONTENT_LEN);
return -EINVAL;
}
if (!cert_cb) {
NET_ERR("Cert callback must be set");
return -EINVAL;
}
if (server_banner) {
new_server(ctx, server_banner);
}
ctx->tls.request_buf = request_buf;
ctx->tls.request_buf_len = request_buf_len;
ctx->is_tls = true;
ctx->tls.stack = stack;
ctx->tls.stack_size = stack_size;
ctx->tls.mbedtls.cert_cb = cert_cb;
ctx->tls.pool = pool;
if (entropy_src_cb) {
ctx->tls.mbedtls.entropy_src_cb = entropy_src_cb;
} else {
ctx->tls.mbedtls.entropy_src_cb = _net_app_entropy_source;
}
ctx->tls.mbedtls.personalization_data = personalization_data;
ctx->tls.mbedtls.personalization_data_len = personalization_data_len;
ctx->send_data = _net_app_tls_sendto;
ctx->recv_cb = _net_app_tls_received;
/* Then mbedtls specific initialization */
return 0;
}
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
bool net_app_server_enable(struct net_app_ctx *ctx)
{
bool old;
NET_ASSERT(ctx);
old = ctx->is_enabled;
ctx->is_enabled = true;
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
if (ctx->is_tls) {
_net_app_server_tls_enable(ctx);
}
#endif
return old;
}
bool net_app_server_disable(struct net_app_ctx *ctx)
{
bool old;
NET_ASSERT(ctx);
old = ctx->is_enabled;
ctx->is_enabled = false;
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
if (ctx->is_tls) {
_net_app_server_tls_disable(ctx);
}
#endif
return old;
}