net: app: Remove net-app API files

The net-app API is removed. Users should use the BSD socket API
for application development.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2019-01-30 10:06:42 +02:00
parent 05f411523d
commit d1162600e9
24 changed files with 5 additions and 6234 deletions

View file

@ -1,220 +0,0 @@
.. _net_app_api:
Network Application API
#######################
The Network Application (net-app) API allows applications to:
**Initialize**
The application for networking use. This means, for example,
that if the application needs to have an IPv4 address, and if DHCPv4 is
enabled, then the net-app API will make sure that the device will get an
IPv4 address before the application is started.
**Set**
Various options for the networking subsystem. This means that if the
user has set options like IP addresses, IEEE 802.15.4 channel etc. in the
project configuration file, then those settings are applied to the system
before the application starts.
**Create**
A simple TCP/UDP server or client application. The net-app API
has functions that make it easy to create a simple TCP or UDP based network
application. The net-app API also provides transparent TLS and DTLS support
for the application.
The net-app API functionality is enabled by :option:`CONFIG_NET_APP` option.
The current net-app API implementation is still experimental and may change and
improve in future releases.
Initialization
**************
The net-app API provides a :cpp:func:`net_app_init()` function that can
configure the networking subsystem for the application. The following
configuration options control this configuration:
:option:`CONFIG_NET_CONFIG_AUTO_INIT`
automatically configures the system according to other configuration options.
The user does not need to call :cpp:func:`net_app_init()` in this case as that
function will be automatically called when the system boots. This option is
enabled by default.
:option:`CONFIG_NET_CONFIG_INIT_TIMEOUT`
specifies how long to wait for the network configuration during the system
boot. For example, if DHCPv4 is enabled, and if the IPv4 address discovery
takes too long or the DHCPv4 server is not found, the system will resume
booting after this number of seconds.
:option:`CONFIG_NET_CONFIG_NEED_IPV6`
specifies that the application needs IPv6 connectivity. The
:cpp:func:`net_app_init()` function will wait until it is able to setup an
IPv6 address for the system before continuing. This means that the IPv6
duplicate address detection (DAD) has finished and the system has properly
setup the IPv6 address.
:option:`CONFIG_NET_CONFIG_NEED_IPV6_ROUTER`
specifies that the application needs IPv6 router connectivity; i.e., it needs
access to external networks (such as the Internet). The
:cpp:func:`net_app_init()` function will wait until it receives a router
advertisement (RA) message from the IPv6 router before continuing.
:option:`CONFIG_NET_CONFIG_NEED_IPV4`
specifies that the application needs IPv4 connectivity. The
:cpp:func:`net_app_init()` function will wait, unless a static IP address is
configured, until it is able to setup an IPv4 address for the network
subsystem.
Setup
*****
Various system level network configuration options can be added to the project
configuration file. These settings are enabled by the
:option:`CONFIG_NET_CONFIG_SETTINGS` configuration option. This option is disabled
by default, and other net-app options may also be disabled by default if
generic support for the networking feature is disabled. For example, the IPv6
net-app options are only available if generic IPv6 support is enabled.
:option:`CONFIG_NET_CONFIG_MY_IPV6_ADDR`
This option sets a static IPv6 address for the system. This is typically only
useful in device testing as normally the system should use SLAAC (IPv6
Stateless Address Auto Configuration), which is enabled by default in the
system. The system can be configured to use multiple IPv6 addresses; this is
controlled by the :option:`CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT`
configuration option.
:option:`CONFIG_NET_CONFIG_PEER_IPV6_ADDR`
This option specifies what is the peer device IPv6 address. This is only
useful when testing client/server type applications. This peer address is
typically used as a parameter when calling :cpp:func:`net_app_connect()`.
:option:`CONFIG_NET_CONFIG_MY_IPV4_ADDR`
This option sets a static IPv4 address for the system. This is typically
useful only in device testing as normally the system should use DHCPv4 to
discover the IPv4 address.
:option:`CONFIG_NET_CONFIG_PEER_IPV4_ADDR`
This option specifies what is the peer device IPv4 address. This is only
useful when testing client/server type applications. This peer address is
typically used as a parameter when connecting to other device.
The following options are only available if IEEE 802.15.4 wireless network
technology support is enabled.
:option:`CONFIG_NET_CONFIG_IEEE802154_DEV_NAME`
This option specifies the name of the IEEE 802.15.4 device.
:option:`CONFIG_NET_CONFIG_IEEE802154_PAN_ID`
This option specifies the used PAN identifier.
Note that the PAN id can be changed at runtime if needed.
:option:`CONFIG_NET_CONFIG_IEEE802154_CHANNEL`
This option specifies the used radio channel.
Note that the used channel can be changed at runtime if needed.
:option:`CONFIG_NET_CONFIG_IEEE802154_RADIO_TX_POWER`
This option specifies the initial radio TX power level. The TX power level can
be changed at runtime if needed.
:option:`CONFIG_NET_CONFIG_IEEE802154_SECURITY_KEY`
This option specifies the initially used security key. The security key can be
changed at runtime if needed.
:option:`CONFIG_NET_CONFIG_IEEE802154_SECURITY_KEY_MODE`
This option specifies the initially used security key mode. The security key
mode can be changed at runtime if needed.
:option:`CONFIG_NET_CONFIG_IEEE802154_SECURITY_LEVEL`
This option specifies the initially used security level. The used security
level can be changed at runtime if needed.
Client / Server Applications
****************************
The net-app API provides functions that enable the application to create
client / server applications easily. If needed, the applications can
have the communication secured by TLS (for TCP connections) or DTLS (for
UDP connections) automatically.
A simple **TCP server** application would make the following net-app API
function calls:
* :cpp:func:`net_app_init_tcp_server()` to configure a local address and TCP
port.
* :cpp:func:`net_app_set_cb()` to configure callback functions to invoke in
response to events, such as data reception.
* :cpp:func:`net_app_server_tls()` will optionally setup the system for secured
connections. To enable the TLS server, also call the
:cpp:func:`net_app_server_tls_enable()` function.
* :cpp:func:`net_app_listen()` will start listening for new client connections.
Creating a **UDP server** is also very easy:
* :cpp:func:`net_app_init_udp_server()` to configure a local address and UDP
port.
* :cpp:func:`net_app_set_cb()` to configure callback functions to invoke in
response to events, such as data reception.
* :cpp:func:`net_app_server_tls()` will optionally setup the system for secured
connections. To enable the DTLS server, also call the
:cpp:func:`net_app_server_tls_enable()` function.
* :cpp:func:`net_app_listen()` will start listening for new client connections.
If the server wants to stop listening for connections, it can call
:cpp:func:`net_app_release()`. After this, if the application wants to start
listening for incoming connections again, it must call the server
initialization functions.
For TLS/DTLS connections, the server can be disabled by a call to
:cpp:func:`net_app_server_tls_disable()`. There are separate enable/disable
functions for TLS support because we need a separate crypto thread for calling
mbedtls crypto API functions. The enable/disable TLS functions will
either create the TLS thread or kill it.
A simple **TCP client** application would make the following net-app API
function calls:
* :cpp:func:`net_app_init_tcp_client()` to configure a local address, peer
address and TCP port. If the DNS resolver support is enabled in the
project configuration file, then the peer address can be given as a hostname,
and the API tries to resolve it to IP address before connecting.
* :cpp:func:`net_app_set_cb()` to configure callback functions to invoke in
response to events, such as data reception.
* :cpp:func:`net_app_client_tls()` will optionally setup the system for secured
connections. The TLS crypto thread will be automatically created when the
application calls :cpp:func:`net_app_connect()` function.
* :cpp:func:`net_app_connect()` will initiate a new connection to the peer host.
Creating a **UDP client** is also very easy:
* :cpp:func:`net_app_init_udp_client()` to configure a local address, peer
address and UDP port. If peer name is a hostname, then it will be
automatically resolved to IP address if DNS resolver is enabled.
* :cpp:func:`net_app_set_cb()` to configure callback functions to invoke in
response to events, such as data reception.
* :cpp:func:`net_app_client_tls()` will optionally setup the system for secured
connections. The DTLS crypto thread will be automatically created when the
application calls :cpp:func:`net_app_connect()` function.
* :cpp:func:`net_app_connect()` will initiate a new connection to the peer host.
As the UDP is connectionless protocol, this function is very simple and it
will just call the connected callback if that is defined.
As both the ``echo_server`` and ``echo_client`` applications use net-app API
functions, please see those applications for more detailed usage examples.
The `net-tools`_ project has information how to test the system if TLS and
DTLS support is enabled. See the **README** file in that project for more
information.
.. _`net-tools`: https://github.com/zephyrproject-rtos/net-tools

View file

@ -1,994 +0,0 @@
/** @file
* @brief Common routines needed in various network applications.
*/
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_NET_NET_APP_H_
#define ZEPHYR_INCLUDE_NET_NET_APP_H_
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
#if defined(CONFIG_MBEDTLS)
#if !defined(CONFIG_MBEDTLS_CFG_FILE)
#include "mbedtls/config.h"
#else
#include CONFIG_MBEDTLS_CFG_FILE
#endif /* CONFIG_MBEDTLS_CFG_FILE */
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_time_t time_t
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif /* MBEDTLS_PLATFORM_C */
#include <mbedtls/ssl_cookie.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/net_sockets.h>
#include <mbedtls/x509.h>
#include <mbedtls/x509_crt.h>
#include <mbedtls/ssl.h>
#include <mbedtls/error.h>
#include <mbedtls/debug.h>
#endif /* CONFIG_MBEDTLS */
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
#include <net/net_ip.h>
#include <net/net_pkt.h>
#include <net/net_context.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Network application library
* @defgroup net_app Network Application Library
* @ingroup networking
* @{
*/
enum net_app_type {
NET_APP_UNSPEC = 0,
NET_APP_SERVER,
NET_APP_CLIENT,
} __packed;
struct net_app_ctx;
/**
* @typedef net_app_recv_cb_t
* @brief Network data receive callback.
*
* @details The recv callback is called after a network data is
* received.
*
* @param ctx The context to use.
* @param pkt Network buffer that is received. If the pkt is not NULL,
* then the callback will own the buffer and it needs to to unref the pkt
* as soon as it has finished working with it. On EOF, pkt will be NULL.
* @param status Value is set to 0 if some data or the connection is
* at EOF, <0 if there was an error receiving data, in this case the
* pkt parameter is set to NULL.
* @param user_data The user data given in init call.
*/
typedef void (*net_app_recv_cb_t)(struct net_app_ctx *ctx,
struct net_pkt *pkt,
int status,
void *user_data);
/**
* @typedef net_app_connect_cb_t
* @brief Connection callback.
*
* @details The connect callback is called after a connection is being
* established.
*
* @param ctx The context to use.
* @param status Status of the connection establishment. This is 0
* if the connection was established successfully, <0 if there was an
* error.
* @param user_data The user data given in init call.
*/
typedef void (*net_app_connect_cb_t)(struct net_app_ctx *ctx,
int status,
void *user_data);
/**
* @typedef net_app_send_cb_t
* @brief Network data send callback.
*
* @details The send callback is called after a network data is
* sent.
*
* @param ctx The context to use.
* @param status Value is set to 0 if all data was sent ok, <0 if
* there was an error sending data. >0 amount of data that was
* sent when not all data was sent ok.
* @param user_data_send The user data given in net_app_send() call.
* @param user_data The user data given in init call.
*/
typedef void (*net_app_send_cb_t)(struct net_app_ctx *ctx,
int status,
void *user_data_send,
void *user_data);
/**
* @typedef net_app_close_cb_t
* @brief Close callback.
*
* @details The close callback is called after a connection is being
* shutdown.
*
* @param ctx The context to use.
* @param status Error code for the closing.
* @param user_data The user data given in init call.
*/
typedef void (*net_app_close_cb_t)(struct net_app_ctx *ctx,
int status,
void *user_data);
/** Network application callbacks */
struct net_app_cb {
/** Function that is called when a connection is established.
*/
net_app_connect_cb_t connect;
/** Function that is called when data is received from network.
*/
net_app_recv_cb_t recv;
/** Function that is called when net_pkt is sent.
*/
net_app_send_cb_t send;
/** Function that is called when connection is shutdown.
*/
net_app_close_cb_t close;
};
/* This is the same prototype as what net_context_sendto() has
* so that we can override the sending of the data for TLS traffic.
*/
typedef int (*net_app_send_data_t)(struct net_pkt *pkt,
const struct sockaddr *dst_addr,
socklen_t addrlen,
net_context_send_cb_t cb,
s32_t timeout,
void *token,
void *user_data);
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
/* Internal information for managing TLS data */
struct tls_context {
struct net_pkt *rx_pkt;
struct net_buf *hdr; /* IP + UDP/TCP header */
struct net_buf *frag;
struct k_sem tx_sem;
struct k_fifo tx_rx_fifo;
int remaining;
#if defined(CONFIG_NET_APP_DTLS) && defined(CONFIG_NET_APP_SERVER)
char client_id;
#endif
};
/* This struct is used to pass data to TLS thread when reading or sending
* data.
*/
struct net_app_fifo_block {
struct k_mem_block block;
struct net_pkt *pkt;
void *token; /* Used when sending data */
net_context_send_cb_t cb;
u8_t dir;
};
#define NET_APP_TLS_POOL_DEFINE(name, count) \
K_MEM_POOL_DEFINE(name, sizeof(struct net_app_fifo_block), \
sizeof(struct net_app_fifo_block), count, sizeof(int))
#if defined(CONFIG_NET_APP_SERVER)
/**
* @typedef net_app_cert_cb_t
* @brief Callback used when the API user needs to setup the certs.
*
* @param ctx Net app context.
* @param cert MBEDTLS certificate
* @param pkey MBEDTLS private key
*
* @return 0 if ok, <0 if there is an error
*/
typedef int (*net_app_cert_cb_t)(struct net_app_ctx *ctx,
mbedtls_x509_crt *cert,
mbedtls_pk_context *pkey);
#endif /* CONFIG_NET_APP_SERVER */
#if defined(CONFIG_NET_APP_CLIENT)
/**
* @typedef net_app_ca_cert_cb_t
* @brief Callback used when the API user needs to setup certs.
*
* @param ctx Net app client context.
* @param ca_cert MBEDTLS certificate. This is of type mbedtls_x509_crt
* if MBEDTLS_X509_CRT_PARSE_C is defined.
*
* @return 0 if ok, <0 if there is an error
*/
typedef int (*net_app_ca_cert_cb_t)(struct net_app_ctx *ctx,
void *ca_cert);
#endif /* CONFIG_NET_APP_CLIENT */
/**
* @typedef net_app_entropy_src_cb_t
* @brief Callback used when the API user needs to setup the entropy source.
* @details This is the same as mbedtls_entropy_f_source_ptr callback.
*
* @param data Callback-specific data pointer
* @param output Data to fill
* @param len Maximum size to provide
* @param olen The actual amount of bytes put into the buffer (Can be 0)
*/
typedef int (*net_app_entropy_src_cb_t)(void *data, unsigned char *output,
size_t len, size_t *olen);
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
#if defined(CONFIG_NET_APP_DTLS)
struct dtls_timing_context {
u32_t snapshot;
u32_t int_ms;
u32_t fin_ms;
};
#endif /* CONFIG_NET_APP_DTLS */
/* Information for the context and local/remote addresses used. */
struct net_app_endpoint {
/** Network context. */
struct net_context *ctx;
/** Local address */
struct sockaddr local;
/** Remote address */
struct sockaddr remote;
};
/** Network application context. */
struct net_app_ctx {
#if defined(CONFIG_NET_IPV6)
struct net_app_endpoint ipv6;
#endif
#if defined(CONFIG_NET_IPV4)
struct net_app_endpoint ipv4;
#endif
/** What is the default endpoint for this context. */
struct net_app_endpoint *default_ctx;
/** Internal function that is called when user data is sent to
* network. By default this is set to net_context_sendto() but
* is overridden for TLS as it requires special handling.
*/
net_app_send_data_t send_data;
/** Connection callbacks */
struct net_app_cb cb;
/** Internal function that is called when data is received from
* network. This will do what ever needed and then pass data to
* application.
*/
net_context_recv_cb_t recv_cb;
#if defined(CONFIG_NET_APP_DTLS)
struct {
/** Currently active network context. This will contain the
* new context that is created after connection is established
* when UDP and DTLS is used.
*/
struct net_context *ctx;
/** DTLS final timer. Connection is terminated if this expires.
*/
struct k_delayed_work fin_timer;
} dtls;
#endif
#if defined(CONFIG_NET_APP_SERVER)
struct {
#if defined(CONFIG_NET_TCP)
/** Currently active network contexts. This will contain the
* new contexts that are created after connection is accepted
* when TCP is enabled.
*/
struct net_context *net_ctxs[CONFIG_NET_APP_SERVER_NUM_CONN];
#endif
} server;
#endif /* CONFIG_NET_APP_SERVER */
#if defined(CONFIG_NET_APP_CLIENT)
struct {
/** Connect waiter */
struct k_sem connect_wait;
#if defined(CONFIG_DNS_RESOLVER)
/** DNS resolver waiter */
struct k_sem dns_wait;
/** DNS query id. This is needed if the query needs to be
* cancelled.
*/
u16_t dns_id;
#endif
} client;
#endif /* CONFIG_NET_APP_CLIENT */
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
struct {
/** TLS stack for mbedtls library. */
k_thread_stack_t *stack;
/** TLS stack size. */
int stack_size;
/** TLS thread id */
k_tid_t tid;
/** TLS thread */
struct k_thread thread;
/** Memory pool for RX data */
struct k_mem_pool *pool;
/** Where the encrypted request is stored, this is to be
* provided by the user.
*/
u8_t *request_buf;
/** Hostname to be used in the certificate verification */
const char *cert_host;
/** Request buffer maximum length */
size_t request_buf_len;
/** mbedtls related configuration. */
struct {
#if defined(CONFIG_NET_APP_SERVER)
net_app_cert_cb_t cert_cb;
mbedtls_x509_crt srvcert;
mbedtls_pk_context pkey;
#endif
#if defined(CONFIG_NET_APP_CLIENT)
net_app_ca_cert_cb_t ca_cert_cb;
mbedtls_x509_crt ca_cert;
#endif
struct tls_context ssl_ctx;
net_app_entropy_src_cb_t entropy_src_cb;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
#if defined(CONFIG_NET_APP_DTLS)
mbedtls_ssl_cookie_ctx cookie_ctx;
struct dtls_timing_context timing_ctx;
#endif
u8_t *personalization_data;
size_t personalization_data_len;
} mbedtls;
/** Have we called connect cb yet? */
u8_t connect_cb_called : 1;
/** User wants to close the connection */
u8_t close_requested : 1;
/** Is there TX pending? If there is then the close operation
* will be postponed after we have sent the data.
*/
u8_t tx_pending : 1;
/** Is the TLS/DTLS handshake fully done */
u8_t handshake_done : 1;
/** Is the connection closing */
u8_t connection_closing : 1;
} tls;
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
/** Network packet (net_pkt) memory pool for network contexts attached
* to this network app context.
*/
net_pkt_get_slab_func_t tx_slab;
/** Network data net_buf pool for network contexts attached to this
* network app context.
*/
net_pkt_get_pool_func_t data_pool;
#endif
/** User data pointer */
void *user_data;
#if CONFIG_NET_APP_LOG_LEVEL >= LOG_LEVEL_DBG
/** Used when debugging with net-shell */
sys_snode_t node;
#endif
/** Type of the connection (stream or datagram) */
enum net_sock_type sock_type;
/** IP protocol type (UDP or TCP) */
enum net_ip_protocol proto;
/** Application type (client or server) of this instance */
enum net_app_type app_type;
/** Is this context setup or not */
u8_t is_init : 1;
/** Is this instance supporting TLS or not.
*/
u8_t is_tls : 1;
/** Running status of the server. If true, then the server is enabled.
* If false then it is disabled and will not serve clients.
* The server is disabled by default after initialization and needs to
* be manually enabled in order to serve any requests.
*/
u8_t is_enabled : 1;
/** Unused bits */
u8_t _padding : 5;
};
#if defined(CONFIG_NET_CONTEXT_NET_PKT_POOL)
/**
* @brief Configure the net_pkt pool for this context.
*
* @details Use of this function is optional and if the pools are not set,
* then the default TX and DATA pools are used.
*
* @param tx_slab Function which is used when allocating TX network packet.
* This can be NULL in which case default TX memory pool is used.
* @param data_pool Function which is used when allocating data network buffer.
* This can be NULL in which case default DATA net_buf pool is used.
*/
int net_app_set_net_pkt_pool(struct net_app_ctx *ctx,
net_pkt_get_slab_func_t tx_slab,
net_pkt_get_pool_func_t data_pool);
#else
#define net_app_set_net_pkt_pool(...)
#endif /* CONFIG_NET_CONTEXT_NET_PKT_POOL */
#if defined(CONFIG_NET_APP_SERVER)
/**
* @brief Create a network server application.
*
* @details Note that caller must create the context and initialize it to 0
* before calling this function. The context must be valid for the whole
* duration of the application life cycle. This usually means that it
* cannot be allocated from stack.
*
* @param ctx Network application context.
* @param sock_type Connection type (stream or datagram).
* @param proto IP protocol (UDP or TCP)
* @param server_addr Local address of the server. If set to NULL, then the
* API will figure out a proper address where to bind the context.
* @param port UDP or TCP port number where the service is located. This is
* only used if server_addr parameter is NULL.
* @param timeout Timeout for this function call. This timeout tells how
* long to wait while accepting the data from network.
* @param user_data User specific data.
*
* @return 0 if ok, <0 if error.
*/
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);
/**
* @brief Create a TCP server application.
*
* @details Note that caller must create the context and initialize it to 0
* before calling this function. The context must be valid for the whole
* duration of the application life cycle. This usually means that it
* cannot be allocated from stack.
*
* @param ctx Network application context.
* @param server_addr Local address of the server. If set to NULL, then the
* API will figure out a proper address where to bind the context.
* @param port UDP or TCP port number where the service is located. This is
* only used if server_addr parameter is NULL.
* @param timeout Timeout for this function call. This timeout tells how
* long to wait while accepting the data from network.
* @param user_data User specific data.
*
* @return 0 if ok, <0 if error.
*/
static inline int net_app_init_tcp_server(struct net_app_ctx *ctx,
struct sockaddr *server_addr,
u16_t port,
void *user_data)
{
return net_app_init_server(ctx,
SOCK_STREAM,
IPPROTO_TCP,
server_addr,
port,
user_data);
}
/**
* @brief Create a UDP server application.
*
* @details Note that caller must create the context and initialize it to 0
* before calling this function. The context must be valid for the whole
* duration of the application life cycle. This usually means that it
* cannot be allocated from stack.
*
* @param ctx Network application context.
* @param server_addr Local address of the server. If set to NULL, then the
* API will figure out a proper address where to bind the context.
* @param port UDP or TCP port number where the service is located. This is
* only used if server_addr parameter is NULL.
* @param timeout Timeout for this function call. This timeout tells how
* long to wait while accepting the data from network.
* @param user_data User specific data.
*
* @return 0 if ok, <0 if error.
*/
static inline int net_app_init_udp_server(struct net_app_ctx *ctx,
struct sockaddr *server_addr,
u16_t port,
void *user_data)
{
return net_app_init_server(ctx,
SOCK_DGRAM,
IPPROTO_UDP,
server_addr,
port,
user_data);
}
/**
* @brief Wait for an incoming connection.
*
* @details Note that caller must have called net_app_init_server() before
* calling this function. This functionality is separated from init function
* so that user can setup the callbacks after calling init. Only after calling
* this function the server starts to listen connection attempts. This function
* will not block but will initialize the local end point address so that
* receive callback will be called for incoming connection.
*
* @param ctx Network application context.
*
* @return 0 if ok, <0 if error.
*/
int net_app_listen(struct net_app_ctx *ctx);
/**
* @brief Enable server to serve connections.
*
* @details By default the server status is disabled.
*
* @param ctx Network application context.
*
* @return 0 if ok, <0 if error.
*/
bool net_app_server_enable(struct net_app_ctx *ctx);
/**
* @brief Disable server so that it will not serve any clients.
*
* @param ctx Network application context.
*
* @return 0 if ok, <0 if error.
*/
bool net_app_server_disable(struct net_app_ctx *ctx);
#endif /* CONFIG_NET_APP_SERVER */
#if defined(CONFIG_NET_APP_CLIENT)
/**
* @brief Create a network client application.
*
* @details Note that caller must create the context and initialize it to 0
* before calling this function. The context must be valid for the whole
* duration of the application life cycle. This usually means that it
* cannot be allocated from stack.
*
* @param ctx Network application context.
* @param sock_type Connection type (stream or datagram).
* @param proto IP protocol (UDP or TCP)
* @param client_addr Local address of the client. If set to NULL, then the
* API will figure out a proper address where to bind the context.
* @param peer_addr Peer (target) address. If this is NULL, then the
* peer_add_str string and peer_port are used when connecting to peer.
* @param peer_addr_str Peer (target) address as a string. If this is NULL,
* then the peer_addr sockaddr is used to set the peer address. If DNS is
* configured in the system, then the hostname is automatically resolved if
* given here. Note that the port number is optional in the string. If the
* port number is not given in the string, then peer_port variable is used
* instead.
* Following syntax is supported for the address:
* 192.0.2.1
* 192.0.2.1:5353
* 2001:db8::1
* [2001:db8::1]:5353
* peer.example.com
* peer.example.com:1234
* @param peer_port Port number where to connect to. Ignored if port number is
* found in the peer_addr_str.
* @param timeout Timeout for this function call. This is used if the API
* needs to do some time consuming operation, like resolving DNS address.
* @param user_data User specific data.
*
* @return 0 if ok, <0 if error.
*/
int net_app_init_client(struct net_app_ctx *ctx,
enum net_sock_type sock_type,
enum net_ip_protocol proto,
struct sockaddr *client_addr,
struct sockaddr *peer_addr,
const char *peer_addr_str,
u16_t peer_port,
s32_t timeout,
void *user_data);
/**
* @brief Create a TCP client application.
*
* @details Note that caller must create the context and initialize it to 0
* before calling this function. The context must be valid for the whole
* duration of the application life cycle. This usually means that it
* cannot be allocated from stack.
*
* @param ctx Network application context.
* @param client_addr Local address of the client. If set to NULL, then the
* API will figure out a proper address where to bind the context.
* @param peer_addr Peer (target) address. If this is NULL, then the
* peer_add_str string and peer_port are used when connecting to peer.
* @param peer_addr_str Peer (target) address as a string. If this is NULL,
* then the peer_addr sockaddr is used to set the peer address. If DNS is
* configured in the system, then the hostname is automatically resolved if
* given here. Note that the port number is optional in the string. If the
* port number is not given in the string, then peer_port variable is used
* instead.
* Following syntax is supported for the address:
* 192.0.2.1
* 192.0.2.1:5353
* 2001:db8::1
* [2001:db8::1]:5353
* peer.example.com
* peer.example.com:1234
* @param peer_port Port number where to connect to. Ignored if port number is
* found in the peer_addr_str.
* @param timeout Timeout for this function call. This is used if the API
* needs to do some time consuming operation, like resolving DNS address.
* @param user_data User specific data.
*
* @return 0 if ok, <0 if error.
*/
static inline int net_app_init_tcp_client(struct net_app_ctx *ctx,
struct sockaddr *client_addr,
struct sockaddr *peer_addr,
const char *peer_addr_str,
u16_t peer_port,
s32_t timeout,
void *user_data)
{
return net_app_init_client(ctx,
SOCK_STREAM,
IPPROTO_TCP,
client_addr,
peer_addr,
peer_addr_str,
peer_port,
timeout,
user_data);
}
/**
* @brief Create a UDP client application.
*
* @details Note that caller must create the context and initialize it to 0
* before calling this function. The context must be valid for the whole
* duration of the application life cycle. This usually means that it
* cannot be allocated from stack.
*
* @param ctx Network application context.
* @param client_addr Local address of the client. If set to NULL, then the
* API will figure out a proper address where to bind the context.
* @param peer_addr Peer (target) address. If this is NULL, then the
* peer_add_str string and peer_port are used when connecting to peer.
* @param peer_addr_str Peer (target) address as a string. If this is NULL,
* then the peer_addr sockaddr is used to set the peer address. If DNS is
* configured in the system, then the hostname is automatically resolved if
* given here. Note that the port number is optional in the string. If the
* port number is not given in the string, then peer_port variable is used
* instead.
* Following syntax is supported for the address:
* 192.0.2.1
* 192.0.2.1:5353
* 2001:db8::1
* [2001:db8::1]:5353
* peer.example.com
* peer.example.com:1234
* @param peer_port Port number where to connect to. Ignored if port number is
* found in the peer_addr_str.
* @param timeout Timeout for this function call. This is used if the API
* needs to do some time consuming operation, like resolving DNS address.
* @param user_data User specific data.
*
* @return 0 if ok, <0 if error.
*/
static inline int net_app_init_udp_client(struct net_app_ctx *ctx,
struct sockaddr *client_addr,
struct sockaddr *peer_addr,
const char *peer_addr_str,
u16_t peer_port,
s32_t timeout,
void *user_data)
{
return net_app_init_client(ctx,
SOCK_DGRAM,
IPPROTO_UDP,
client_addr,
peer_addr,
peer_addr_str,
peer_port,
timeout,
user_data);
}
/**
* @brief Establish a network connection to peer.
*
* @param ctx Network application context.
* @param timeout How long to wait the network connection before giving up.
*
* @return 0 if ok, <0 if error.
*/
int net_app_connect(struct net_app_ctx *ctx, s32_t timeout);
#endif /* CONFIG_NET_APP_CLIENT */
/**
* @brief Set various network application callbacks.
*
* @param ctx Network app context.
* @param connect_cb Connect callback.
* @param recv_cb Data receive callback.
* @param send_cb Data sent callback.
* @param close_cb Close callback.
*
* @return 0 if ok, <0 if error.
*/
int net_app_set_cb(struct net_app_ctx *ctx,
net_app_connect_cb_t connect_cb,
net_app_recv_cb_t recv_cb,
net_app_send_cb_t send_cb,
net_app_close_cb_t close_cb);
/**
* @brief Send data that is found in net_pkt to peer.
*
* @details If the function return < 0, then it is caller responsibility
* to unref the pkt. If the packet was sent successfully, then the lower
* IP stack will release the network pkt.
*
* @param ctx Network application context.
* @param pkt Network packet to send.
* @param dst Destination address where to send packet. This is
* ignored for TCP data.
* @param dst_len Destination address structure size
* @param timeout How long to wait the send before giving up.
* @param user_data_send User data specific to this send call.
*
* @return 0 if ok, <0 if error.
*/
int net_app_send_pkt(struct net_app_ctx *ctx,
struct net_pkt *pkt,
const struct sockaddr *dst,
socklen_t dst_len,
s32_t timeout,
void *user_data_send);
/**
* @brief Send data that is found in user specified buffer to peer.
*
* @param ctx Network application context.
* @param buf Buffer to send.
* @param buf_len Amount of data to send.
* @param dst Destination address where to send packet. This is
* ignored for TCP data.
* @param dst_len Destination address structure size
* @param timeout How long to wait the send before giving up.
* @param user_data_send User data specific to this send call.
*
* @return 0 if ok, <0 if error.
*/
int net_app_send_buf(struct net_app_ctx *ctx,
u8_t *buf,
size_t buf_len,
const struct sockaddr *dst,
socklen_t dst_len,
s32_t timeout,
void *user_data_send);
/**
* @brief Create network packet.
*
* @param ctx Network application context.
* @param family What kind of network packet to get (AF_INET or AF_INET6)
* @param timeout How long to wait the send before giving up.
*
* @return valid net_pkt if ok, NULL if error.
*/
struct net_pkt *net_app_get_net_pkt(struct net_app_ctx *ctx,
sa_family_t family,
s32_t timeout);
/**
* @brief Create network packet based on dst address.
*
* @param ctx Network application context.
* @param dst Destination address to select net_context
* @param timeout How long to wait the send before giving up.
*
* @return valid net_pkt if ok, NULL if error.
*/
struct net_pkt *net_app_get_net_pkt_with_dst(struct net_app_ctx *ctx,
const struct sockaddr *dst,
s32_t timeout);
/**
* @brief Create network buffer that will hold network data.
*
* @details The returned net_buf is automatically appended to the
* end of network packet fragment chain.
*
* @param ctx Network application context.
* @param pkt Network packet to where the data buf is appended.
* @param timeout How long to wait the send before giving up.
*
* @return valid net_pkt if ok, NULL if error.
*/
struct net_buf *net_app_get_net_buf(struct net_app_ctx *ctx,
struct net_pkt *pkt,
s32_t timeout);
/**
* @brief Close a network connection to peer.
*
* @param ctx Network application context.
*
* @return 0 if ok, <0 if error.
*/
int net_app_close(struct net_app_ctx *ctx);
/**
* @brief Close a specific network connection.
*
* @param ctx Network application context.
* @param net_ctx Network context.
*
* @return 0 if ok, <0 if error.
*/
int net_app_close2(struct net_app_ctx *ctx,
struct net_context *net_ctx);
/**
* @brief Release this network application context.
*
* @details No network data will be received via this context after this
* call.
*
* @param ctx Network application context.
*
* @return 0 if ok, <0 if error.
*/
int net_app_release(struct net_app_ctx *ctx);
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
#if defined(CONFIG_NET_APP_CLIENT)
/**
* @brief Initialize TLS support for this net_app client context.
*
* @param ctx net_app context.
* @param request_buf Caller-supplied buffer where the TLS request will be
* stored
* @param request_buf_len Length of the caller-supplied buffer.
* @param personalization_data Personalization data (Device specific
* identifiers) for random number generator. (Can be NULL).
* @param personalization_data_len Length of the personalization data.
* @param cert_cb User-supplied callback that setups the certificates.
* @param cert_host Hostname that is used to verify the server certificate.
* This value is used when net_api API calls mbedtls_ssl_set_hostname()
* which sets the hostname to check against the received server certificate.
* See https://tls.mbed.org/kb/how-to/use-sni for more details.
* This can be left NULL in which case mbedtls will silently skip certificate
* verification entirely. This option is only used if MBEDTLS_X509_CRT_PARSE_C
* is enabled in mbedtls config file.
* @param entropy_src_cb User-supplied callback that setup the entropy. This
* can be set to NULL, in which case default entropy source is used.
* @param pool Memory pool for RX data reads.
* @param stack TLS thread stack.
* @param stack_len TLS thread stack size.
*
* @return Return 0 if ok, <0 if error.
*/
int net_app_client_tls(struct net_app_ctx *ctx,
u8_t *request_buf,
size_t request_buf_len,
u8_t *personalization_data,
size_t personalization_data_len,
net_app_ca_cert_cb_t cert_cb,
const char *cert_host,
net_app_entropy_src_cb_t entropy_src_cb,
struct k_mem_pool *pool,
k_thread_stack_t *stack,
size_t stack_size);
#endif /* CONFIG_NET_APP_CLIENT */
#if defined(CONFIG_NET_APP_SERVER)
/**
* @brief Initialize TLS support for this net_app server context.
*
* @param ctx net_app context.
* @param request_buf Caller-supplied buffer where the TLS request will be
* stored
* @param request_buf_len Length of the caller-supplied buffer.
* @param server_banner Print information about started service. This is only
* printed if net_app debugging is activated. The parameter can be set to NULL
* if no extra prints are needed.
* @param personalization_data Personalization data (Device specific
* identifiers) for random number generator. (Can be NULL).
* @param personalization_data_len Length of the personalization data.
* @param cert_cb User-supplied callback that setups the certificates.
* @param entropy_src_cb User-supplied callback that setup the entropy. This
* can be set to NULL, in which case default entropy source is used.
* @param pool Memory pool for RX data reads.
* @param stack TLS thread stack.
* @param stack_len TLS thread stack size.
*
* @return Return 0 if ok, <0 if error.
*/
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_len);
#endif /* CONFIG_NET_APP_SERVER */
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
/**
* @}
*/
typedef void (*net_app_ctx_cb_t)(struct net_app_ctx *ctx, void *user_data);
void net_app_server_foreach(net_app_ctx_cb_t cb, void *user_data);
void net_app_client_foreach(net_app_ctx_cb_t cb, void *user_data);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_NET_NET_APP_H_ */

View file

@ -21,7 +21,8 @@ source "subsys/net/Kconfig.template.log_config.net"
config NET_L2_ETHERNET_MGMT
bool "Enable Ethernet network management interface"
depends on NET_MGMT && NET_MGMT_EVENT
select NET_MGMT
select NET_MGMT_EVENT
help
Enable support net_mgmt Ethernet interface which can be used to
configure at run-time Ethernet drivers and L2 settings.

View file

@ -3,7 +3,6 @@ add_subdirectory_if_kconfig(lwm2m)
add_subdirectory_if_kconfig(sntp)
add_subdirectory_ifdef(CONFIG_DNS_RESOLVER dns)
add_subdirectory_ifdef(CONFIG_MQTT_LIB mqtt_sock)
add_subdirectory_ifdef(CONFIG_NET_APP app)
add_subdirectory_ifdef(CONFIG_NET_CONFIG_SETTINGS config)
add_subdirectory_ifdef(CONFIG_NET_SOCKETS sockets)
add_subdirectory_ifdef(CONFIG_TLS_CREDENTIALS tls_credentials)

View file

@ -24,8 +24,6 @@ menu "Network Libraries"
source "subsys/net/lib/config/Kconfig"
source "subsys/net/lib/app/Kconfig"
source "subsys/net/lib/sockets/Kconfig"
source "subsys/net/lib/tls_credentials/Kconfig"

View file

@ -1,5 +0,0 @@
zephyr_sources_ifdef(CONFIG_NET_APP_SERVER net_app.c server.c)
zephyr_sources_ifdef(CONFIG_NET_APP_CLIENT net_app.c client.c)
zephyr_link_interface_ifdef(CONFIG_MBEDTLS mbedTLS)
zephyr_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)

View file

@ -1,75 +0,0 @@
# Kconfig.app - Options for networking applications
#
# Copyright (c) 2017 Intel Corporation.
#
# SPDX-License-Identifier: Apache-2.0
#
menuconfig NET_APP
bool "Network application API support [EXPERIMENTAL]"
default y
select NET_MGMT
select NET_MGMT_EVENT
help
Enable API that helps to create client/server network applications.
This API is experimental and subject to change.
if NET_APP
module = NET_APP
module-dep = NET_LOG
module-str = Log level for net_app library
module-help = Enables net app library to output debug messages.
source "subsys/net/Kconfig.template.log_config.net"
config NET_APP_SERVER
bool "Enable server support"
help
Enables net app library server APIs.
config NET_APP_SERVER_NUM_CONN
int "Number of simultaneous incoming connections"
default 1
depends on NET_APP_SERVER
help
Tells how many simultaneous incoming connections the server instance can
support. The value of CONFIG_NET_TCP_BACKLOG_SIZE must be greater than
or equal to CONFIG_NET_APP_SERVER_NUM_CONN.
config NET_APP_CLIENT
bool "Enable client support"
help
Enables net app library client APIs.
config NET_APP_TLS
bool "Enable TLS support for TCP applications"
depends on NET_TCP
select MBEDTLS
help
Enables net app library to use TLS for encrypted communication.
config NET_APP_DTLS
bool "Enable DTLS support for UDP applications"
depends on NET_UDP
select MBEDTLS
help
Enables net app library to use DTLS for encrypted UDP communication.
config NET_APP_DTLS_TIMEOUT
int "DTLS session timeout"
depends on NET_APP_DTLS
default 15
help
If a DTLS session does not have any activity, then disconnect
the session. The value is in seconds.
config NET_APP_TLS_STACK_SIZE
int "TLS handler thread stack size"
default 8192
depends on NET_APP_TLS || NET_APP_DTLS
help
TLS handler thread stack size. The mbedtls routines will use this stack
thus it is by default very large.
endif # NET_APP

View file

@ -1,942 +0,0 @@
/* client.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/dns_resolve.h>
#include <net/net_app.h>
#include "../../ip/udp_internal.h"
#include "net_app_private.h"
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
#define TLS_STARTUP_TIMEOUT K_SECONDS(5)
static int start_tls_client(struct net_app_ctx *ctx);
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
#if defined(CONFIG_DNS_RESOLVER)
static void dns_cb(enum dns_resolve_status status,
struct dns_addrinfo *info,
void *user_data)
{
struct net_app_ctx *ctx = user_data;
if (!(status == DNS_EAI_INPROGRESS && info)) {
return;
}
if (info->ai_family == AF_INET) {
#if defined(CONFIG_NET_IPV4)
net_ipaddr_copy(&net_sin(&ctx->ipv4.remote)->sin_addr,
&net_sin(&info->ai_addr)->sin_addr);
ctx->ipv4.remote.sa_family = info->ai_family;
#else
goto out;
#endif
} else if (info->ai_family == AF_INET6) {
#if defined(CONFIG_NET_IPV6)
net_ipaddr_copy(&net_sin6(&ctx->ipv6.remote)->sin6_addr,
&net_sin6(&info->ai_addr)->sin6_addr);
ctx->ipv6.remote.sa_family = info->ai_family;
#else
goto out;
#endif
} else {
goto out;
}
out:
k_sem_give(&ctx->client.dns_wait);
}
static int resolve_name(struct net_app_ctx *ctx,
const char *peer_addr_str,
enum dns_query_type type,
s32_t timeout)
{
int ret;
k_sem_init(&ctx->client.dns_wait, 0, 1);
ret = dns_get_addr_info(peer_addr_str, type, &ctx->client.dns_id,
dns_cb, ctx, timeout);
if (ret < 0) {
NET_ERR("Cannot resolve %s (%d)", log_strdup(peer_addr_str),
ret);
ctx->client.dns_id = 0;
return ret;
}
/* Wait a little longer for the DNS to finish so that
* the DNS will timeout before the semaphore.
*/
if (k_sem_take(&ctx->client.dns_wait, timeout + K_SECONDS(1))) {
NET_ERR("Timeout while resolving %s",
log_strdup(peer_addr_str));
ctx->client.dns_id = 0;
return -ETIMEDOUT;
}
ctx->client.dns_id = 0;
if (ctx->default_ctx->remote.sa_family == AF_UNSPEC) {
return -EINVAL;
}
return 0;
}
#endif /* CONFIG_DNS_RESOLVER */
static int try_resolve(struct net_app_ctx *ctx,
const char *peer_addr_str,
enum dns_query_type type,
s32_t timeout)
{
#if !defined(CONFIG_DNS_RESOLVER)
return -EINVAL;
#else
int ret;
ret = resolve_name(ctx, peer_addr_str, type, timeout);
if (ret < 0) {
NET_ERR("Cannot resolve %s (%d)",
log_strdup(peer_addr_str), ret);
}
return ret;
#endif
}
static int set_remote_addr(struct net_app_ctx *ctx,
struct sockaddr *remote_addr,
const char *peer_addr_str,
bool peer_addr_ok,
s32_t timeout)
{
int ret;
if (peer_addr_ok && remote_addr->sa_family == AF_INET6) {
#if defined(CONFIG_NET_IPV6)
memcpy(&ctx->ipv6.remote, remote_addr,
sizeof(struct sockaddr));
ctx->default_ctx = &ctx->ipv6;
return 0;
#else
return -EAFNOSUPPORT;
#endif
}
if (peer_addr_ok && remote_addr->sa_family == AF_INET) {
#if defined(CONFIG_NET_IPV4)
memcpy(&ctx->ipv4.remote, remote_addr,
sizeof(struct sockaddr));
ctx->default_ctx = &ctx->ipv4;
return 0;
#else
return -EAFNOSUPPORT;
#endif
}
#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
/* Could be hostname, try DNS if configured. */
ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_AAAA, timeout);
if (ret < 0) {
return ret;
}
ctx->default_ctx = &ctx->ipv6;
return 0;
#endif /* IPV6 && !IPV4 */
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6)
ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_A, timeout);
if (ret < 0) {
return ret;
}
ctx->default_ctx = &ctx->ipv4;
return 0;
#endif /* IPV6 && !IPV4 */
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_A, timeout);
if (ret < 0) {
ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_AAAA,
timeout);
if (ret < 0) {
return ret;
}
ctx->default_ctx = &ctx->ipv6;
return 0;
}
ctx->default_ctx = &ctx->ipv4;
return 0;
#endif /* IPV4 && IPV6 */
}
static int get_port_number(const char *peer_addr_str,
char *buf,
size_t buf_len)
{
u16_t port = 0U;
char *ptr;
int count, i;
if (peer_addr_str[0] == '[') {
#if defined(CONFIG_NET_IPV6)
/* IPv6 address with port number */
int end;
ptr = strstr(peer_addr_str, "]:");
if (!ptr) {
return -EINVAL;
}
end = min(INET6_ADDRSTRLEN, ptr - (peer_addr_str + 1));
memcpy(buf, peer_addr_str + 1, end);
buf[end] = '\0';
port = strtol(ptr + 2, NULL, 10);
return port;
#else
return -EAFNOSUPPORT;
#endif /* CONFIG_NET_IPV6 */
}
count = i = 0;
while (peer_addr_str[i]) {
if (peer_addr_str[i] == ':') {
count++;
}
i++;
}
if (count == 1) {
#if defined(CONFIG_NET_IPV4)
/* IPv4 address with port number */
int end;
ptr = strstr(peer_addr_str, ":");
if (!ptr) {
return -EINVAL;
}
end = min(NET_IPV4_ADDR_LEN, ptr - peer_addr_str);
memcpy(buf, peer_addr_str, end);
buf[end] = '\0';
port = strtol(ptr + 1, NULL, 10);
return port;
#else
return -EAFNOSUPPORT;
#endif /* CONFIG_NET_IPV4 */
}
return 0;
}
static void close_net_ctx(struct net_app_ctx *ctx)
{
#if defined(CONFIG_NET_IPV6)
if (ctx->ipv6.ctx) {
net_context_put(ctx->ipv6.ctx);
ctx->ipv6.ctx = NULL;
}
#endif
#if defined(CONFIG_NET_IPV4)
if (ctx->ipv4.ctx) {
net_context_put(ctx->ipv4.ctx);
ctx->ipv4.ctx = NULL;
}
#endif
#if defined(CONFIG_NET_APP_SERVER) && defined(CONFIG_NET_TCP)
{
int i;
for (i = 0; i < CONFIG_NET_APP_SERVER_NUM_CONN; i++) {
if (ctx->server.net_ctxs[i]) {
net_context_put(ctx->server.net_ctxs[i]);
ctx->server.net_ctxs[i] = NULL;
}
}
}
#endif
}
static int bind_local(struct net_app_ctx *ctx)
{
int ret = 0;
#if defined(CONFIG_NET_IPV4)
if (ctx->ipv4.remote.sa_family == AF_INET && ctx->ipv4.ctx) {
ctx->ipv4.local.sa_family = AF_INET;
_net_app_set_local_addr(ctx, &ctx->ipv4.local, NULL,
ntohs(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) {
net_context_put(ctx->ipv4.ctx);
ctx->ipv4.ctx = NULL;
}
}
#endif
#if defined(CONFIG_NET_IPV6)
if (ctx->ipv6.remote.sa_family == AF_INET6 && ctx->ipv6.ctx) {
ctx->ipv6.local.sa_family = AF_INET6;
_net_app_set_local_addr(ctx, &ctx->ipv6.local, NULL,
ntohs(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) {
net_context_put(ctx->ipv6.ctx);
ctx->ipv6.ctx = NULL;
}
}
#endif
return ret;
}
int net_app_init_client(struct net_app_ctx *ctx,
enum net_sock_type sock_type,
enum net_ip_protocol proto,
struct sockaddr *client_addr,
struct sockaddr *peer_addr,
const char *peer_addr_str,
u16_t peer_port,
s32_t timeout,
void *user_data)
{
const char *base_peer_addr = peer_addr_str;
char base_addr_str[INET6_ADDRSTRLEN + 1];
struct sockaddr remote_addr;
struct sockaddr addr;
int ret, addr_ok = false;
if (!ctx) {
return -EINVAL;
}
if (ctx->is_init) {
return -EALREADY;
}
(void)memset(&addr, 0, sizeof(addr));
(void)memset(&remote_addr, 0, sizeof(remote_addr));
if (peer_addr) {
memcpy(&remote_addr, peer_addr, sizeof(remote_addr));
} else if (peer_addr_str) {
/* If the peer string contains port number, use that and
* ignore the port number parameter.
*/
ret = get_port_number(peer_addr_str, base_addr_str,
sizeof(base_addr_str));
if (ret > 0) {
base_peer_addr = base_addr_str;
peer_port = ret;
} else {
strncpy(base_addr_str, peer_addr_str,
sizeof(base_addr_str) - 1);
}
addr_ok = net_ipaddr_parse(base_peer_addr,
strlen(base_peer_addr),
&remote_addr);
/* The remote_addr will be used by set_remote_addr() to
* set the actual peer address.
*/
}
if (client_addr) {
u16_t local_port = 0U;
bool empty_addr = false;
addr.sa_family = remote_addr.sa_family;
/* local_port is used if the IP address isn't specified */
#if defined(CONFIG_NET_IPV4)
if (client_addr->sa_family == AF_INET) {
empty_addr = net_ipv4_is_addr_unspecified(
&net_sin(client_addr)->sin_addr);
local_port = net_sin(client_addr)->sin_port;
}
#endif
#if defined(CONFIG_NET_IPV6)
if (client_addr->sa_family == AF_INET6) {
empty_addr = net_ipv6_is_addr_unspecified(
&net_sin6(client_addr)->sin6_addr);
local_port = net_sin6(client_addr)->sin6_port;
}
#endif
if (empty_addr) {
if (remote_addr.sa_family == AF_INET6) {
net_sin6(&addr)->sin6_port = local_port;
} else {
net_sin(&addr)->sin_port = local_port;
}
} else {
memcpy(&addr, client_addr, sizeof(addr));
if (addr.sa_family != remote_addr.sa_family) {
NET_DBG("Address family mismatch %d vs %d",
addr.sa_family, remote_addr.sa_family);
return -EINVAL;
}
}
} else {
addr.sa_family = remote_addr.sa_family;
}
ctx->app_type = NET_APP_CLIENT;
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;
ctx->is_enabled = true;
ret = _net_app_config_local_ctx(ctx, sock_type, proto, &addr);
if (ret < 0) {
close_net_ctx(ctx);
goto fail;
}
if (peer_addr) {
if (peer_addr->sa_family == AF_INET) {
#if defined(CONFIG_NET_IPV4)
memcpy(&ctx->ipv4.remote, peer_addr,
sizeof(ctx->ipv4.remote));
ctx->default_ctx = &ctx->ipv4;
#else
return -EPROTONOSUPPORT;
#endif
} else if (peer_addr->sa_family == AF_INET6) {
#if defined(CONFIG_NET_IPV6)
memcpy(&ctx->ipv6.remote, peer_addr,
sizeof(ctx->ipv6.remote));
ctx->default_ctx = &ctx->ipv6;
#else
return -EPROTONOSUPPORT;
#endif
}
goto out;
}
if (!peer_addr_str) {
NET_ERR("Cannot know where to connect.");
ret = -EINVAL;
close_net_ctx(ctx);
goto fail;
}
ret = set_remote_addr(ctx, &remote_addr, base_addr_str,
addr_ok, timeout);
if (ret < 0) {
close_net_ctx(ctx);
goto fail;
}
/* If we have not yet figured out what is the protocol family,
* then we cannot continue.
*/
if (!ctx->default_ctx ||
ctx->default_ctx->remote.sa_family == AF_UNSPEC) {
NET_ERR("Unknown protocol family.");
return -EPFNOSUPPORT;
}
/* Set the port now that we know the sa_family */
if (!peer_addr) {
#if defined(CONFIG_NET_IPV6)
if (ctx->default_ctx->remote.sa_family == AF_INET6) {
net_sin6(&ctx->default_ctx->remote)->sin6_port =
htons(peer_port);
}
#endif
#if defined(CONFIG_NET_IPV4)
if (ctx->default_ctx->remote.sa_family == AF_INET) {
net_sin(&ctx->default_ctx->remote)->sin_port =
htons(peer_port);
}
#endif
}
ret = bind_local(ctx);
if (ret < 0) {
goto fail;
}
_net_app_print_info(ctx);
out:
ctx->is_init = true;
_net_app_register(ctx);
fail:
return ret;
}
static void _app_connected(struct net_context *net_ctx,
int status,
void *user_data)
{
struct net_app_ctx *ctx = user_data;
int ret;
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
if (ctx->is_tls) {
k_sem_give(&ctx->client.connect_wait);
}
#endif
ret = net_context_recv(net_ctx, ctx->recv_cb, K_NO_WAIT, ctx);
if (ret < 0) {
NET_DBG("Cannot set recv_cb (%d)", ret);
}
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
if (ctx->is_tls) {
/* If we have TLS connection, the connect cb is called
* after TLS handshakes are done.
*/
NET_DBG("Postponing TLS connection cb for ctx %p", ctx);
} else
#endif
{
if (ctx->cb.connect) {
ctx->cb.connect(ctx, status, ctx->user_data);
}
}
}
#if defined(CONFIG_NET_APP_DTLS)
static int connect_dtls(struct net_app_ctx *ctx, struct net_context *orig,
struct sockaddr *remote)
{
struct net_context *dtls_context;
struct sockaddr local_addr;
int ret;
/* We create a new context that starts to send data and get replies
* directly into correct callback.
*/
ret = net_context_get(net_context_get_family(orig), SOCK_DGRAM,
IPPROTO_UDP, &dtls_context);
if (ret < 0) {
NET_DBG("Cannot get connect context");
goto out;
}
memcpy(&dtls_context->remote, remote, sizeof(dtls_context->remote));
#if defined(CONFIG_NET_IPV6)
if (net_context_get_family(orig) == AF_INET6) {
struct sockaddr_in6 *local_addr6 = net_sin6(&local_addr);
net_sin6(&dtls_context->remote)->sin6_family = AF_INET6;
local_addr6->sin6_family = AF_INET6;
local_addr6->sin6_port = net_sin6_ptr(&orig->local)->sin6_port;
net_ipaddr_copy(&local_addr6->sin6_addr,
net_sin6_ptr(&orig->local)->sin6_addr);
} else
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
if (net_context_get_family(orig) == AF_INET) {
struct sockaddr_in *local_addr4 = net_sin(&local_addr);
net_sin(&dtls_context->remote)->sin_family = AF_INET;
local_addr4->sin_family = AF_INET;
local_addr4->sin_port = net_sin_ptr(&orig->local)->sin_port;
net_ipaddr_copy(&local_addr4->sin_addr,
net_sin_ptr(&orig->local)->sin_addr);
} else
#endif /* CONFIG_NET_IPV4 */
{
NET_ASSERT_INFO(false, "Invalid protocol family %d",
net_context_get_family(orig));
goto ctx_drop;
}
ret = net_context_bind(dtls_context, &local_addr, sizeof(local_addr));
if (ret < 0) {
NET_DBG("Cannot bind connect DTLS context");
goto ctx_drop;
}
dtls_context->flags |= NET_CONTEXT_REMOTE_ADDR_SET;
ret = net_udp_register(&dtls_context->remote,
&local_addr,
ntohs(net_sin(&dtls_context->remote)->sin_port),
ntohs(net_sin(&local_addr)->sin_port),
_net_app_dtls_established,
ctx,
&dtls_context->conn_handler);
if (ret < 0) {
NET_DBG("Cannot register connect DTLS handler (%d)", ret);
goto ctx_drop;
}
NET_DBG("New DTLS connection context %p created", dtls_context);
ctx->dtls.ctx = dtls_context;
return 0;
ctx_drop:
net_context_unref(dtls_context);
out:
return -ECONNABORTED;
}
#endif /* CONFIG_NET_APP_DTLS */
static void check_local_address(struct net_app_ctx *ctx,
struct net_context *net_ctx)
{
#if defined(CONFIG_NET_IPV6)
if (net_context_get_family(net_ctx) == AF_INET6) {
const struct in6_addr *laddr;
struct in6_addr *raddr;
laddr = &net_sin6(&ctx->ipv6.local)->sin6_addr;
if (!net_ipv6_is_addr_unspecified(laddr)) {
return;
}
raddr = &net_sin6(&ctx->ipv6.remote)->sin6_addr;
laddr = net_if_ipv6_select_src_addr(NULL, raddr);
if (laddr && laddr != net_ipv6_unspecified_address()) {
net_ipaddr_copy(&net_sin6(&ctx->ipv6.local)->sin6_addr,
laddr);
} else {
NET_WARN("Source address is unspecified!");
}
}
#endif
#if defined(CONFIG_NET_IPV4)
if (net_context_get_family(net_ctx) == AF_INET) {
struct in_addr *laddr;
struct net_if *iface;
laddr = &net_sin(&ctx->ipv4.local)->sin_addr;
if (!net_ipv4_is_addr_unspecified(laddr)) {
return;
}
/* Just take the first IPv4 address of an interface */
iface = net_context_get_iface(net_ctx);
if (iface) {
laddr =
&iface->config.ip.ipv4->unicast[0].address.in_addr;
net_ipaddr_copy(&net_sin(&ctx->ipv4.local)->sin_addr,
laddr);
} else {
NET_WARN("Source address is unspecified!");
}
}
#endif
}
int net_app_connect(struct net_app_ctx *ctx, s32_t timeout)
{
struct net_context *net_ctx;
bool started = false;
int ret;
if (!ctx) {
return -EINVAL;
}
if (!ctx->is_init) {
return -ENOENT;
}
if (ctx->app_type != NET_APP_CLIENT) {
return -EINVAL;
}
net_ctx = _net_app_select_net_ctx(ctx, NULL);
if (!net_ctx && ctx->is_enabled) {
return -EAFNOSUPPORT;
}
if (!ctx->is_enabled) {
ret = _net_app_config_local_ctx(ctx, ctx->sock_type,
ctx->proto, NULL);
if (ret < 0) {
NET_DBG("Cannot get local endpoint (%d)", ret);
return -EINVAL;
}
net_ctx = _net_app_select_net_ctx(ctx, NULL);
NET_DBG("Re-conncting to net_ctx %p", net_ctx);
ret = bind_local(ctx);
if (ret < 0) {
NET_DBG("Cannot bind local endpoint (%d)", ret);
return -EINVAL;
}
ctx->is_enabled = true;
_net_app_print_info(ctx);
} else {
/* We cannot bind to local unspecified address when sending.
* Select proper address depending on remote one in this case.
*/
check_local_address(ctx, net_ctx);
}
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
if (ctx->is_tls && !ctx->tls.tid &&
(ctx->proto == IPPROTO_TCP ||
(IS_ENABLED(CONFIG_NET_APP_DTLS) && ctx->proto == IPPROTO_UDP))) {
/* TLS thread is not yet running, start it now */
ret = start_tls_client(ctx);
if (ret < 0) {
NET_DBG("TLS thread cannot be started (%d)", ret);
return ret;
}
started = true;
/* Let the TLS thread run first */
k_yield();
}
#else
ARG_UNUSED(started);
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
#if defined(CONFIG_NET_APP_DTLS)
if (ctx->proto == IPPROTO_UDP) {
if (!ctx->dtls.ctx) {
ret = connect_dtls(ctx, net_ctx,
&ctx->default_ctx->remote);
if (ret < 0) {
return ret;
}
ret = net_context_connect(ctx->dtls.ctx,
&ctx->dtls.ctx->remote,
sizeof(ctx->dtls.ctx->remote),
_app_connected,
timeout,
ctx);
} else {
/* If we have already a connection, then we cannot
* really continue.
*/
ret = -EAGAIN;
}
} else
#endif /* CONFIG_NET_APP_DTLS */
{
ret = net_context_connect(net_ctx,
&ctx->default_ctx->remote,
sizeof(ctx->default_ctx->remote),
_app_connected,
timeout,
ctx);
}
if (ret < 0) {
NET_DBG("Cannot connect to peer (%d)", ret);
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
if (started) {
_net_app_tls_handler_stop(ctx);
}
#endif
}
return ret;
}
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
static void tls_client_handler(struct net_app_ctx *ctx,
struct k_sem *startup_sync)
{
int ret;
NET_DBG("Starting TLS client thread for %p", ctx);
ret = _net_app_tls_init(ctx, MBEDTLS_SSL_IS_CLIENT);
if (ret < 0) {
NET_DBG("TLS client init failed");
return;
}
k_sem_give(startup_sync);
while (1) {
/* We wait until TLS connection is established */
k_sem_take(&ctx->client.connect_wait, K_FOREVER);
ret = _net_app_ssl_mainloop(ctx);
if (ctx->tls.connection_closing) {
mbedtls_ssl_close_notify(&ctx->tls.mbedtls.ssl);
if (ctx->cb.close) {
ctx->cb.close(ctx, -ESHUTDOWN, ctx->user_data);
}
ctx->tls.connection_closing = false;
ctx->is_enabled = false;
/* Wait more connection requests from user */
continue;
}
if (ret < 0) {
NET_ERR("TLS mainloop startup failed (%d)", ret);
break;
}
}
NET_DBG("Shutting down TLS handler");
/* If there is any pending data that have not been processed
* yet, we need to free it here.
*/
if (ctx->tls.mbedtls.ssl_ctx.rx_pkt) {
net_pkt_unref(ctx->tls.mbedtls.ssl_ctx.rx_pkt);
ctx->tls.mbedtls.ssl_ctx.rx_pkt = NULL;
ctx->tls.mbedtls.ssl_ctx.frag = NULL;
}
if (ctx->cb.close) {
ctx->cb.close(ctx, -ESHUTDOWN, ctx->user_data);
}
_net_app_tls_handler_stop(ctx);
}
static int start_tls_client(struct net_app_ctx *ctx)
{
struct k_sem startup_sync;
/* Start the thread that handles TLS traffic. */
if (ctx->tls.tid) {
return -EALREADY;
}
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_client_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_app_tls_handler_stop(ctx);
return -ECANCELED;
}
return 0;
}
int net_app_client_tls(struct net_app_ctx *ctx,
u8_t *request_buf,
size_t request_buf_len,
u8_t *personalization_data,
size_t personalization_data_len,
net_app_ca_cert_cb_t cert_cb,
const char *cert_host,
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;
}
ctx->is_tls = true;
ctx->send_data = _net_app_tls_sendto;
ctx->recv_cb = _net_app_tls_received;
ctx->tls.request_buf = request_buf;
ctx->tls.request_buf_len = request_buf_len;
ctx->tls.cert_host = cert_host;
ctx->tls.stack = stack;
ctx->tls.stack_size = stack_size;
ctx->tls.mbedtls.ca_cert_cb = cert_cb;
ctx->tls.pool = pool;
ctx->tls.mbedtls.personalization_data = personalization_data;
ctx->tls.mbedtls.personalization_data_len = personalization_data_len;
if (entropy_src_cb) {
ctx->tls.mbedtls.entropy_src_cb = entropy_src_cb;
} else {
ctx->tls.mbedtls.entropy_src_cb = _net_app_entropy_source;
}
/* The semaphore is released when the client calls net_app_connect() */
k_sem_init(&ctx->client.connect_wait, 0, 1);
/* The mbedtls is initialized in TLS thread because of mbedtls stack
* requirements. TLS thread is started when we get the first client
* request to send data.
*/
return 0;
}
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */

File diff suppressed because it is too large Load diff

View file

@ -1,118 +0,0 @@
/** @file
* @brief Private net_api API routines
*/
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Print extra info about received TLS data */
#define RX_EXTRA_DEBUG 0
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#include <mbedtls/memory_buffer_alloc.h>
#endif
#if defined(MBEDTLS_ERROR_C)
#define _net_app_print_error(fmt, ret) \
do { \
char error[80]; \
\
mbedtls_strerror(ret, error, sizeof(error)); \
\
NET_ERR(fmt " (%s)", -ret, log_strdup(error)); \
} while (0)
#else
#define _net_app_print_error(fmt, ret) NET_ERR(fmt, -ret)
#endif
/* Direction of the packet (sending / receiving) */
enum _net_app_dir {
NET_APP_PKT_UNKNOWN = 0,
NET_APP_PKT_TX = 1,
NET_APP_PKT_RX = 2,
};
#define BUF_ALLOC_TIMEOUT 100
void _net_app_print_info(struct net_app_ctx *ctx);
#if defined(CONFIG_NET_APP_SERVER) || defined(CONFIG_NET_APP_CLIENT)
char *_net_app_sprint_ipaddr(char *buf, int buflen,
const struct sockaddr *addr);
void _net_app_received(struct net_context *net_ctx,
struct net_pkt *pkt,
int status,
void *user_data);
int _net_app_set_local_addr(struct net_app_ctx *ctx, struct sockaddr *addr,
const char *myaddr, u16_t port);
int _net_app_set_net_ctx(struct net_app_ctx *ctx,
struct net_context *net_ctx,
struct sockaddr *addr,
socklen_t socklen,
enum net_ip_protocol proto);
int _net_app_config_local_ctx(struct net_app_ctx *ctx,
enum net_sock_type sock_type,
enum net_ip_protocol proto,
struct sockaddr *addr);
#if CONFIG_NET_APP_LOG_LEVEL >= LOG_LEVEL_ERR
struct net_context *_net_app_select_net_ctx_debug(struct net_app_ctx *ctx,
const struct sockaddr *dst,
const char *caller,
int line);
#define _net_app_select_net_ctx(ctx, dst) \
_net_app_select_net_ctx_debug(ctx, dst, __func__, __LINE__)
#else
struct net_context *_net_app_select_net_ctx(struct net_app_ctx *ctx,
const struct sockaddr *dst);
#endif
int _net_app_ssl_mux(void *context, unsigned char *buf, size_t size);
int _net_app_tls_sendto(struct net_pkt *pkt,
const struct sockaddr *dst_addr,
socklen_t addrlen,
net_context_send_cb_t cb,
s32_t timeout,
void *token,
void *user_data);
void _net_app_tls_received(struct net_context *context,
struct net_pkt *pkt,
int status,
void *user_data);
int _net_app_ssl_mainloop(struct net_app_ctx *ctx);
int _net_app_tls_trigger_close(struct net_app_ctx *ctx);
#if defined(CONFIG_NET_APP_SERVER)
void _net_app_accept_cb(struct net_context *net_ctx,
struct sockaddr *addr,
socklen_t addrlen,
int status, void *data);
#endif /* CONFIG_NET_APP_SERVER */
#if defined(CONFIG_NET_APP_CLIENT)
#endif /* CONFIG_NET_APP_CLIENT */
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
bool _net_app_server_tls_enable(struct net_app_ctx *ctx);
bool _net_app_server_tls_disable(struct net_app_ctx *ctx);
void _net_app_tls_handler_stop(struct net_app_ctx *ctx);
int _net_app_tls_init(struct net_app_ctx *ctx, int client_or_server);
int _net_app_entropy_source(void *data, unsigned char *output, size_t len,
size_t *olen);
int _net_app_ssl_tx(void *context, const unsigned char *buf, size_t size);
#endif /* CONFIG_NET_APP_TLS || CONFIG_NET_APP_DTLS */
#if defined(CONFIG_NET_APP_DTLS)
#include "../../ip/connection.h"
enum net_verdict _net_app_dtls_established(struct net_conn *conn,
struct net_pkt *pkt,
void *user_data);
#endif /* CONFIG_NET_APP_DTLS */
void _net_app_register(struct net_app_ctx *ctx);
void _net_app_unregister(struct net_app_ctx *ctx);
#endif /* CONFIG_NET_APP_SERVER || CONFIG_NET_APP_CLIENT */

View file

@ -1,516 +0,0 @@
/* 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;
}

View file

@ -9,3 +9,6 @@ zephyr_sources(
zephyr_sources_ifdef(CONFIG_NET_SOCKETS_SOCKOPT_TLS sockets_tls.c)
endif()
zephyr_sources_ifdef(CONFIG_NET_SOCKETS_OFFLOAD socket_offload.c)
zephyr_link_interface_ifdef(CONFIG_MBEDTLS mbedTLS)
zephyr_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS)

View file

@ -1,8 +0,0 @@
cmake_minimum_required(VERSION 3.13.1)
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
project(net_app)
FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE ${app_sources})
target_include_directories(app PRIVATE $ENV{ZEPHYR_BASE}/subsys/net/ip)

View file

@ -1,29 +0,0 @@
CONFIG_NETWORKING=y
CONFIG_NET_TEST=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=n
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_NET_DHCPV4=n
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_L2_DUMMY=y
CONFIG_NET_LOG=y
CONFIG_ENTROPY_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_IPV6_DAD=n
CONFIG_NET_IPV6_MLD=n
CONFIG_NET_IPV6_ND=n
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=10
CONFIG_NET_BUF_TX_COUNT=10
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=6
CONFIG_NET_IPV6_MAX_NEIGHBORS=8
CONFIG_NET_APP=y
CONFIG_NET_APP_SERVER=y
CONFIG_NET_APP_CLIENT=y
CONFIG_NET_CONFIG_AUTO_INIT=n
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
CONFIG_ZTEST=y
#CONFIG_NET_SHELL=y

View file

@ -1,25 +0,0 @@
CONFIG_NETWORKING=y
CONFIG_NET_TEST=y
CONFIG_NET_IPV6=n
CONFIG_NET_IPV4=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_NET_DHCPV4=n
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_L2_DUMMY=y
CONFIG_NET_LOG=y
CONFIG_ENTROPY_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=10
CONFIG_NET_BUF_TX_COUNT=10
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_NET_APP=y
CONFIG_NET_APP_SERVER=y
CONFIG_NET_APP_CLIENT=y
CONFIG_NET_CONFIG_AUTO_INIT=n
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
CONFIG_ZTEST=y
#CONFIG_NET_SHELL=y

View file

@ -1,43 +0,0 @@
CONFIG_NETWORKING=y
CONFIG_NET_TEST=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_NET_DHCPV4=n
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_L2_DUMMY=y
CONFIG_NET_LOG=y
CONFIG_ENTROPY_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_IPV6_DAD=n
CONFIG_NET_IPV6_MLD=n
CONFIG_NET_IPV6_ND=n
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=10
CONFIG_NET_BUF_TX_COUNT=10
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=6
CONFIG_NET_IPV6_MAX_NEIGHBORS=8
CONFIG_NET_APP=y
CONFIG_NET_APP_SERVER=y
CONFIG_NET_APP_CLIENT=y
CONFIG_NET_CONFIG_AUTO_INIT=n
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
CONFIG_ZTEST=y
CONFIG_DNS_RESOLVER=y
CONFIG_DNS_RESOLVER_MAX_SERVERS=4
CONFIG_DNS_NUM_CONCUR_QUERIES=1
CONFIG_DNS_SERVER_IP_ADDRESSES=y
CONFIG_DNS_SERVER1="192.0.2.2"
CONFIG_DNS_SERVER2="2001:db8::2"
CONFIG_DNS_SERVER3="192.0.2.2:5353"
CONFIG_DNS_SERVER4="[2001:db8::2]:5353"
#CONFIG_NET_SHELL=y
CONFIG_COVERAGE=n

View file

@ -1,31 +0,0 @@
CONFIG_NETWORKING=y
CONFIG_NET_TEST=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_NET_DHCPV4=n
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_L2_DUMMY=y
CONFIG_NET_LOG=y
CONFIG_ENTROPY_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_IPV6_DAD=n
CONFIG_NET_IPV6_MLD=n
CONFIG_NET_IPV6_ND=n
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=10
CONFIG_NET_BUF_TX_COUNT=10
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=6
CONFIG_NET_IPV6_MAX_NEIGHBORS=8
CONFIG_NET_APP=y
CONFIG_NET_APP_SERVER=y
CONFIG_NET_APP_CLIENT=y
CONFIG_NET_CONFIG_AUTO_INIT=n
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
CONFIG_ZTEST=y

View file

@ -1,812 +0,0 @@
/* main.c - Application main entry point */
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <logging/log.h>
LOG_MODULE_REGISTER(net_test, CONFIG_NET_APP_LOG_LEVEL);
#include <zephyr/types.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <misc/printk.h>
#include <ztest.h>
#include <net/ethernet.h>
#include <net/dummy.h>
#include <net/buf.h>
#include <net/net_ip.h>
#include <net/net_if.h>
#include <net/net_config.h>
#include <net/net_app.h>
#define NET_LOG_ENABLED 1
#include "net_private.h"
#if defined(CONFIG_NET_APP_LOG_LEVEL_DBG)
#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
#else
#define DBG(fmt, ...)
#endif
#if defined(CONFIG_NET_IPV6)
/* Interface 1 addresses */
static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
/* Interface 2 addresses */
static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
/* Extra address is assigned to ll_addr */
static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0,
0, 0, 0, 0xf2, 0xaa, 0x29, 0x02,
0x04 } } };
static struct in6_addr in6addr_mcast = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
#endif
#if defined(CONFIG_NET_IPV4)
/* Interface 1 addresses IPv4 */
static struct in_addr my_addr4 = { { { 192, 0, 1, 1 } } };
#endif
static struct net_if *iface1;
static bool test_failed;
static bool test_started;
static struct k_sem wait_data;
#define WAIT_TIME 250
struct net_if_test {
u8_t idx;
u8_t mac_addr[sizeof(struct net_eth_addr)];
struct net_linkaddr ll_addr;
};
static int net_iface_dev_init(struct device *dev)
{
return 0;
}
static u8_t *net_iface_get_mac(struct device *dev)
{
struct net_if_test *data = dev->driver_data;
if (data->mac_addr[2] == 0x00) {
/* 00-00-5E-00-53-xx Documentation RFC 7042 */
data->mac_addr[0] = 0x00;
data->mac_addr[1] = 0x00;
data->mac_addr[2] = 0x5E;
data->mac_addr[3] = 0x00;
data->mac_addr[4] = 0x53;
data->mac_addr[5] = sys_rand32_get();
}
data->ll_addr.addr = data->mac_addr;
data->ll_addr.len = 6;
return data->mac_addr;
}
static void net_iface_init(struct net_if *iface)
{
u8_t *mac = net_iface_get_mac(net_if_get_device(iface));
net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr),
NET_LINK_ETHERNET);
}
static int sender_iface(struct device *dev, struct net_pkt *pkt)
{
if (!pkt->frags) {
DBG("No data to send!\n");
return -ENODATA;
}
if (test_started) {
struct net_if_test *data = dev->driver_data;
if (net_if_get_by_iface(net_pkt_iface(pkt)) != data->idx) {
DBG("Invalid interface %d index, expecting %d\n",
data->idx, net_if_get_by_iface(net_pkt_iface(pkt)));
test_failed = true;
}
}
k_sem_give(&wait_data);
return 0;
}
struct net_if_test net_iface1_data;
static struct dummy_api net_iface_api = {
.iface_api.init = net_iface_init,
.send = sender_iface,
};
#define _ETH_L2_LAYER DUMMY_L2
#define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)
NET_DEVICE_INIT_INSTANCE(net_iface1_test,
"iface1",
iface1,
net_iface_dev_init,
&net_iface1_data,
NULL,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&net_iface_api,
_ETH_L2_LAYER,
_ETH_L2_CTX_TYPE,
127);
static void iface_setup(void)
{
#if defined(CONFIG_NET_IPV6)
struct net_if_mcast_addr *maddr;
#endif
struct net_if_addr *ifaddr;
int idx;
/* The semaphore is there to wait the data to be received. */
k_sem_init(&wait_data, 0, UINT_MAX);
iface1 = net_if_get_by_index(0);
((struct net_if_test *)net_if_get_device(iface1)->driver_data)->idx = 0U;
idx = net_if_get_by_iface(iface1);
zassert_equal(idx, 0, "Invalid index iface1");
DBG("Interfaces: [%d] iface1 %p\n",
net_if_get_by_iface(iface1), iface1);
zassert_not_null(iface1, "Interface 1");
#if defined(CONFIG_NET_IPV6)
ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1,
NET_ADDR_MANUAL, 0);
if (!ifaddr) {
DBG("Cannot add IPv6 address %s\n",
net_sprint_ipv6_addr(&my_addr1));
zassert_not_null(ifaddr, "addr1");
}
/* For testing purposes we need to set the adddresses preferred */
ifaddr->addr_state = NET_ADDR_PREFERRED;
ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr,
NET_ADDR_MANUAL, 0);
if (!ifaddr) {
DBG("Cannot add IPv6 address %s\n",
net_sprint_ipv6_addr(&ll_addr));
zassert_not_null(ifaddr, "ll_addr");
}
ifaddr->addr_state = NET_ADDR_PREFERRED;
net_ipv6_addr_create(&in6addr_mcast, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
maddr = net_if_ipv6_maddr_add(iface1, &in6addr_mcast);
if (!maddr) {
DBG("Cannot add multicast IPv6 address %s\n",
net_sprint_ipv6_addr(&in6addr_mcast));
zassert_not_null(maddr, "mcast");
}
#endif /* IPv6 */
#if defined(CONFIG_NET_IPV4)
ifaddr = net_if_ipv4_addr_add(iface1, &my_addr4,
NET_ADDR_MANUAL, 0);
if (!ifaddr) {
DBG("Cannot add IPv4 address %s\n",
net_sprint_ipv4_addr(&my_addr4));
zassert_not_null(ifaddr, "addr4");
}
#endif
net_if_up(iface1);
/* The interface might receive data which might fail the checks
* in the iface sending function, so we need to reset the failure
* flag.
*/
test_failed = false;
test_started = true;
}
static void app_init(void)
{
int ret;
ret = net_config_init("Test app", 0, 1);
zassert_equal(ret, 0, "app init");
}
static struct net_app_ctx udp_server_ctx;
static struct net_app_ctx tcp_server_ctx;
static void app_udp_server_init(void)
{
int ret;
ret = net_app_init_udp_server(&udp_server_ctx, NULL, 42421, NULL);
zassert_equal(ret, 0, "UDP server init");
}
static void app_tcp_server_init(void)
{
int ret;
ret = net_app_init_tcp_server(&tcp_server_ctx, NULL, 42422, NULL);
zassert_equal(ret, 0, "TCP server init");
}
static void app_udp_server_listen(void)
{
int ret;
net_app_server_enable(&udp_server_ctx);
ret = net_app_listen(&udp_server_ctx);
zassert_equal(ret, 0, "UDP listen failed");
}
static void app_tcp_server_listen(void)
{
int ret;
net_app_server_enable(&tcp_server_ctx);
ret = net_app_listen(&tcp_server_ctx);
zassert_equal(ret, 0, "TCP listen failed");
}
static void app_tcp6_client_peer(void)
{
#if defined(CONFIG_NET_IPV6)
static struct net_app_ctx ctx;
int port;
int ret;
ret = net_app_init_tcp_client(&ctx,
NULL,
NULL,
"2001:db8:200::1",
42422,
0,
NULL);
zassert_equal(ret, 0, "TCP IPv6 client init");
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
zassert_equal(port, 42422, "TCP port invalid");
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
&my_addr2);
zassert_equal(ret, true, "IPv6 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "TCP IPv6 client close");
#endif
}
static void app_tcp4_client_peer(void)
{
#if defined(CONFIG_NET_IPV4)
static struct net_app_ctx ctx;
int port;
int ret;
ret = net_app_init_tcp_client(&ctx,
NULL,
NULL,
"192.0.1.1",
42422,
0,
NULL);
zassert_equal(ret, 0, "TCP IPv4 client init");
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
zassert_equal(port, 42422, "TCP port invalid");
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
&my_addr4);
zassert_equal(ret, true, "IPv4 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "TCP IPv4 client close");
#endif
}
static void app_udp6_client_peer(void)
{
#if defined(CONFIG_NET_IPV6)
static struct net_app_ctx ctx;
int port;
int ret;
ret = net_app_init_udp_client(&ctx,
NULL,
NULL,
"2001:db8:200::1",
42421,
0,
NULL);
zassert_equal(ret, 0, "UDP IPv6 client init");
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
zassert_equal(port, 42421, "UDP port invalid");
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
&my_addr2);
zassert_equal(ret, true, "IPv6 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "UDP IPv6 client close");
#endif
}
static void app_udp4_client_peer(void)
{
#if defined(CONFIG_NET_IPV4)
static struct net_app_ctx ctx;
int port;
int ret;
ret = net_app_init_udp_client(&ctx,
NULL,
NULL,
"192.0.1.1",
42421,
0,
NULL);
zassert_equal(ret, 0, "TCP IPv4 client init");
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
zassert_equal(port, 42421, "UDP port invalid");
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
&my_addr4);
zassert_equal(ret, true, "IPv4 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "UDP IPv4 client close");
#endif
}
static void app_tcp6_client_peer_with_port(void)
{
#if defined(CONFIG_NET_IPV6)
static struct net_app_ctx ctx;
int port;
int ret;
ret = net_app_init_tcp_client(&ctx,
NULL,
NULL,
"[2001:db8:200::1]:1234",
42422,
0,
NULL);
zassert_equal(ret, 0, "TCP IPv6 client init");
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
zassert_equal(port, 1234, "TCP port invalid");
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
&my_addr2);
zassert_equal(ret, true, "IPv6 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "TCP IPv6 client close");
#endif
}
static void app_tcp4_client_peer_with_port(void)
{
#if defined(CONFIG_NET_IPV4)
static struct net_app_ctx ctx;
int port;
int ret;
ret = net_app_init_tcp_client(&ctx,
NULL,
NULL,
"192.0.1.1:1234",
42422,
0,
NULL);
zassert_equal(ret, 0, "TCP IPv4 client init");
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
zassert_equal(port, 1234, "TCP port invalid");
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
&my_addr4);
zassert_equal(ret, true, "IPv4 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "TCP IPv4 client close");
#endif
}
static void app_udp6_client_peer_with_port(void)
{
#if defined(CONFIG_NET_IPV6)
static struct net_app_ctx ctx;
int port;
int ret;
ret = net_app_init_udp_client(&ctx,
NULL,
NULL,
"[2001:db8:200::1]:9999",
42421,
0,
NULL);
zassert_equal(ret, 0, "UDP IPv6 client init");
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
zassert_equal(port, 9999, "UDP port invalid");
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
&my_addr2);
zassert_equal(ret, true, "IPv6 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "UDP IPv6 client close");
#endif
}
static void app_udp4_client_peer_with_port(void)
{
#if defined(CONFIG_NET_IPV4)
static struct net_app_ctx ctx;
int port;
int ret;
ret = net_app_init_udp_client(&ctx,
NULL,
NULL,
"192.0.1.1:9999",
42421,
0,
NULL);
zassert_equal(ret, 0, "TCP IPv4 client init");
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
zassert_equal(port, 9999, "UDP port invalid");
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
&my_addr4);
zassert_equal(ret, true, "IPv4 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "UDP IPv4 client close");
#endif
}
static void app_tcp6_client_peer_addr(void)
{
#if defined(CONFIG_NET_IPV6)
static struct net_app_ctx ctx;
struct sockaddr_in6 peer;
int port;
int ret;
net_ipaddr_copy(&peer.sin6_addr, &my_addr2);
peer.sin6_port = htons(8765);
peer.sin6_family = AF_INET6;
ret = net_app_init_tcp_client(&ctx,
NULL,
(struct sockaddr *)&peer,
"foobar",
42422,
0,
NULL);
zassert_equal(ret, 0, "TCP IPv6 client init");
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
zassert_equal(port, 8765, "TCP port invalid");
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
&my_addr2);
zassert_equal(ret, true, "IPv6 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "TCP IPv6 client close");
#endif
}
static void app_tcp4_client_peer_addr(void)
{
#if defined(CONFIG_NET_IPV4)
static struct net_app_ctx ctx;
struct sockaddr_in peer;
int port;
int ret;
net_ipaddr_copy(&peer.sin_addr, &my_addr4);
peer.sin_port = htons(8765);
peer.sin_family = AF_INET;
ret = net_app_init_tcp_client(&ctx,
NULL,
(struct sockaddr *)&peer,
"foobar",
42422,
0,
NULL);
zassert_equal(ret, 0, "TCP IPv4 client init");
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
zassert_equal(port, 8765, "TCP port invalid");
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
&my_addr4);
zassert_equal(ret, true, "IPv4 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "TCP IPv4 client close");
#endif
}
static void app_udp6_client_peer_addr(void)
{
#if defined(CONFIG_NET_IPV6)
static struct net_app_ctx ctx;
struct sockaddr_in6 peer;
int port;
int ret;
net_ipaddr_copy(&peer.sin6_addr, &my_addr2);
peer.sin6_port = htons(8765);
peer.sin6_family = AF_INET6;
ret = net_app_init_udp_client(&ctx,
NULL,
(struct sockaddr *)&peer,
"foobar",
42422,
0,
NULL);
zassert_equal(ret, 0, "UDP IPv6 client init");
port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port);
zassert_equal(port, 8765, "UDP port invalid");
ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr,
&my_addr2);
zassert_equal(ret, true, "IPv6 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "UDP IPv6 client close");
#endif
}
static void app_udp4_client_peer_addr(void)
{
#if defined(CONFIG_NET_IPV4)
static struct net_app_ctx ctx;
struct sockaddr_in peer;
int port;
int ret;
net_ipaddr_copy(&peer.sin_addr, &my_addr4);
peer.sin_port = htons(8765);
peer.sin_family = AF_INET;
ret = net_app_init_udp_client(&ctx,
NULL,
(struct sockaddr *)&peer,
"foobar",
42422,
0,
NULL);
zassert_equal(ret, 0, "UDP IPv4 client init");
port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port);
zassert_equal(port, 8765, "UDP port invalid");
ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr,
&my_addr4);
zassert_equal(ret, true, "IPv4 address mismatch");
ret = net_app_close(&ctx);
zassert_equal(ret, 0, "UDP IPv4 client close");
#endif
}
static void app_tcp6_client_hostname_fail(void)
{
#if defined(CONFIG_NET_IPV6)
static struct net_app_ctx ctx;
int ret;
ret = net_app_init_tcp_client(&ctx,
NULL,
NULL,
"foobar",
42422,
0,
NULL);
zassert_equal(ret, -EINVAL, "TCP IPv6 client init");
#endif
}
static void app_tcp4_client_hostname_fail(void)
{
#if defined(CONFIG_NET_IPV4)
static struct net_app_ctx ctx;
int ret;
ret = net_app_init_tcp_client(&ctx,
NULL,
NULL,
"foobar",
42422,
0,
NULL);
zassert_equal(ret, -EINVAL, "TCP IPv4 client init");
#endif
}
static void app_udp6_client_hostname_fail(void)
{
#if defined(CONFIG_NET_IPV6)
static struct net_app_ctx ctx;
int ret;
ret = net_app_init_udp_client(&ctx,
NULL,
NULL,
"foobar",
42422,
0,
NULL);
zassert_equal(ret, -EINVAL, "UDP IPv6 client init");
#endif
}
static void app_udp4_client_hostname_fail(void)
{
#if defined(CONFIG_NET_IPV4)
static struct net_app_ctx ctx;
int ret;
ret = net_app_init_udp_client(&ctx,
NULL,
NULL,
"foobar",
42422,
0,
NULL);
zassert_equal(ret, -EINVAL, "UDP IPv4 client init");
#endif
}
static void app_tcp6_client_hostname(void)
{
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_DNS_RESOLVER)
static struct net_app_ctx ctx;
int ret;
ret = net_app_init_tcp_client(&ctx,
NULL,
NULL,
"foobar",
42422,
MSEC(100),
NULL);
zassert_equal(ret, -ETIMEDOUT, "TCP IPv6 client init");
#endif
}
static void app_tcp4_client_hostname(void)
{
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_DNS_RESOLVER)
static struct net_app_ctx ctx;
int ret;
ret = net_app_init_tcp_client(&ctx,
NULL,
NULL,
"foobar",
42422,
MSEC(100),
NULL);
zassert_equal(ret, -ETIMEDOUT, "TCP IPv4 client init");
#endif
}
static void app_udp6_client_hostname(void)
{
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_DNS_RESOLVER)
static struct net_app_ctx ctx;
int ret;
ret = net_app_init_udp_client(&ctx,
NULL,
NULL,
"foobar",
42422,
MSEC(100),
NULL);
zassert_equal(ret, -ETIMEDOUT, "UDP IPv6 client init");
#endif
}
static void app_udp4_client_hostname(void)
{
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_DNS_RESOLVER)
static struct net_app_ctx ctx;
int ret;
ret = net_app_init_udp_client(&ctx,
NULL,
NULL,
"foobar",
42422,
MSEC(100),
NULL);
zassert_equal(ret, -ETIMEDOUT, "UDP IPv4 client init");
#endif
}
static void app_close_server(void)
{
int ret;
ret = net_app_close(&udp_server_ctx);
zassert_equal(ret, 0, "UDP server close");
ret = net_app_close(&tcp_server_ctx);
zassert_equal(ret, 0, "TCP server close");
}
void test_main(void)
{
ztest_test_suite(net_app_test,
ztest_unit_test(iface_setup),
ztest_unit_test(app_init),
ztest_unit_test(app_udp_server_init),
ztest_unit_test(app_tcp_server_init),
ztest_unit_test(app_udp_server_listen),
ztest_unit_test(app_tcp_server_listen),
ztest_unit_test(app_tcp6_client_peer),
ztest_unit_test(app_udp6_client_peer),
ztest_unit_test(app_tcp4_client_peer),
ztest_unit_test(app_udp4_client_peer),
ztest_unit_test(app_tcp6_client_peer_with_port),
ztest_unit_test(app_tcp4_client_peer_with_port),
ztest_unit_test(app_udp6_client_peer_with_port),
ztest_unit_test(app_udp4_client_peer_with_port),
ztest_unit_test(app_tcp6_client_peer_addr),
ztest_unit_test(app_tcp4_client_peer_addr),
ztest_unit_test(app_udp6_client_peer_addr),
ztest_unit_test(app_udp4_client_peer_addr),
ztest_unit_test(app_tcp6_client_hostname_fail),
ztest_unit_test(app_tcp4_client_hostname_fail),
ztest_unit_test(app_udp6_client_hostname_fail),
ztest_unit_test(app_udp4_client_hostname_fail),
ztest_unit_test(app_tcp6_client_hostname),
ztest_unit_test(app_tcp4_client_hostname),
ztest_unit_test(app_udp6_client_hostname),
ztest_unit_test(app_udp4_client_hostname),
ztest_unit_test(app_close_server)
);
ztest_run_test_suite(net_app_test);
}

View file

@ -1,19 +0,0 @@
common:
depends_on: netif
platform_whitelist: native_posix qemu_x86 qemu_cortex_m3
tests:
net.app:
min_ram: 32
tags: net
net.app.no-ipv4:
extra_args: CONF_FILE=prj-no-ipv4.conf
min_ram: 32
tags: net
net.app.no-ipv6:
extra_args: CONF_FILE=prj-no-ipv6.conf
min_ram: 32
tags: net
net.app.with-dns:
extra_args: CONF_FILE=prj-with-dns.conf
min_ram: 32
tags: net dns

View file

@ -21,7 +21,6 @@ CONFIG_NET_IF_MAX_IPV4_COUNT=2
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
CONFIG_NET_IPV6_ND=n
CONFIG_ZTEST=y
CONFIG_NET_APP=n
CONFIG_NET_CONFIG_SETTINGS=n
CONFIG_NET_SHELL=n

View file

@ -19,7 +19,6 @@ CONFIG_NET_IF_MAX_IPV6_COUNT=6
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
CONFIG_NET_IPV6_ND=n
CONFIG_ZTEST=y
CONFIG_NET_APP=n
CONFIG_NET_CONFIG_SETTINGS=n
CONFIG_NET_SHELL=n
CONFIG_PTP_CLOCK=y

View file

@ -28,7 +28,6 @@ CONFIG_NET_CONTEXT_PRIORITY=y
CONFIG_NET_TC_TX_COUNT=8
CONFIG_NET_TC_RX_COUNT=8
CONFIG_ZTEST=y
CONFIG_NET_APP=n
CONFIG_NET_CONFIG_SETTINGS=n
CONFIG_NET_SHELL=n

View file

@ -19,7 +19,6 @@ CONFIG_NET_IF_MAX_IPV6_COUNT=6
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6
CONFIG_NET_IPV6_ND=n
CONFIG_ZTEST=y
CONFIG_NET_APP=n
CONFIG_NET_CONFIG_SETTINGS=n
CONFIG_NET_SHELL=n
CONFIG_NET_PKT_TIMESTAMP=y

View file

@ -23,7 +23,6 @@ CONFIG_NET_VLAN=y
CONFIG_NET_VLAN_COUNT=4
CONFIG_NET_CONTEXT_PRIORITY=y
CONFIG_ZTEST=y
CONFIG_NET_APP=n
CONFIG_NET_CONFIG_SETTINGS=n
CONFIG_NET_SHELL=n