diff options
author | Anas Nashif <nashif@linux.intel.com> | 2017-01-29 04:31:39 +0000 |
---|---|---|
committer | Anas Nashif <nashif@linux.intel.com> | 2017-01-29 04:31:39 +0000 |
commit | 66417c02461ceff8138db452f91b7500ccd763f9 (patch) | |
tree | 7ee1cf30bf92d383164b11aa36ccd8c332759a86 /samples | |
parent | 3d2a5c38f8d32b74d228ac272da1cebf709cdf24 (diff) | |
parent | 7d37e7d51970dab4c95f2508702d8403067076dc (diff) |
Merge "Merge net branch into master"
Diffstat (limited to 'samples')
42 files changed, 2715 insertions, 308 deletions
diff --git a/samples/net/coaps_client/Makefile b/samples/net/coaps_client/Makefile new file mode 100644 index 000000000..8e54ca81d --- /dev/null +++ b/samples/net/coaps_client/Makefile @@ -0,0 +1,14 @@ +# Makefile - CoAP secure client test application + +# +# Copyright (c) 2015 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +BOARD ?= qemu_x86 +CONF_FILE ?= prj_$(BOARD).conf + +include $(ZEPHYR_BASE)/Makefile.inc + +include $(ZEPHYR_BASE)/samples/net/common/Makefile.ipstack diff --git a/samples/net/coaps_client/README.rst b/samples/net/coaps_client/README.rst new file mode 100644 index 000000000..bdc1696cd --- /dev/null +++ b/samples/net/coaps_client/README.rst @@ -0,0 +1,53 @@ +CoAP over DTLS sample client +############################ + +Overview +======== +This sample code shows a CoAP over DTLS client using mbedTLS on top of Zephyr. + +Building and Running +==================== + +Follow the steps for testing :ref:`networking with Qemu <networking_with_qemu>`. + +Run the server application at samples/net/coaps_server, with the following +command: + +.. code-block:: console + + make server + +In other terminal window, run this client application at samples/net/coaps_client: + +.. code-block:: console + + make client + +You will get the following output: + +.. code-block:: console + + reply: 60 45 00 01 ff 54 79 70 65 3a 20 30 0a 43 6f 64 65 3a 20 31 0a 4d + 49 44 3a 20 31 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 (123 bytes) + +From the server application directory the screen should display + +.. code-block:: console + + ******* + type: 0 code 1 id 1 + ******* + connection was closed gracefully + done + +If the server does not receive the messages, restart the app and try to connect +the client again. + +References +========== + +* https://wiki.zephyrproject.org/view/Networking-with-Qemu diff --git a/samples/net/coaps_client/prj_qemu_x86.conf b/samples/net/coaps_client/prj_qemu_x86.conf new file mode 100644 index 000000000..209dd3698 --- /dev/null +++ b/samples/net/coaps_client/prj_qemu_x86.conf @@ -0,0 +1,27 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV6=y +CONFIG_NET_UDP=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_BUF_LOG=y +CONFIG_NET_LOG=y +CONFIG_NET_SLIP_TAP=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_INIT_STACKS=y +CONFIG_PRINTK=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_NBUF_RX_COUNT=14 +CONFIG_NET_NBUF_TX_COUNT=14 +CONFIG_NET_NBUF_DATA_COUNT=30 +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2 +CONFIG_NET_MAX_CONTEXTS=10 + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_CFG_FILE="config-coap.h" + +CONFIG_ZOAP=y + +CONFIG_NET_SAMPLES_IP_ADDRESSES=y +CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::3" +CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::1" diff --git a/samples/net/coaps_client/src/Makefile b/samples/net/coaps_client/src/Makefile new file mode 100644 index 000000000..788664861 --- /dev/null +++ b/samples/net/coaps_client/src/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (c) 2016 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +obj-y += coaps_client.o udp.o diff --git a/samples/net/coaps_client/src/coaps_client.c b/samples/net/coaps_client/src/coaps_client.c new file mode 100644 index 000000000..84f875f74 --- /dev/null +++ b/samples/net/coaps_client/src/coaps_client.c @@ -0,0 +1,447 @@ +/* Sample CoAP over DTLS client using mbedTLS. + * (Meant to be used with config-coap.h) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * SPDX-License-Identifier: Apache-2.0 + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#include <zephyr.h> +#include <stdio.h> +#include <errno.h> +#include <misc/printk.h> + +#if !defined(CONFIG_MBEDTLS_CFG_FILE) +#include "mbedtls/config.h" +#else +#include CONFIG_MBEDTLS_CFG_FILE +#endif + +#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 + +#include <string.h> +#include <net/net_context.h> +#include <net/net_if.h> +#include <net/buf.h> +#include <net/nbuf.h> +#include "udp.h" +#include "udp_cfg.h" + +#include "mbedtls/net.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include <net/zoap.h> + +#if defined(MBEDTLS_DEBUG_C) +#include "mbedtls/debug.h" +#define DEBUG_THRESHOLD 0 +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" +static unsigned char heap[8192]; +#endif + +/* + * Hardcoded values for server host and port + */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +const unsigned char psk[] = "passwd\0"; +const char psk_id[] = "Client_identity\0"; +#endif + +const char *pers = "mini_client"; +static unsigned char payload[128]; + +#define NUM_REPLIES 3 +struct zoap_reply replies[NUM_REPLIES]; + +#define ZOAP_BUF_SIZE 128 + +NET_BUF_POOL_DEFINE(zoap_nbuf_pool, 4, 0, sizeof(struct net_nbuf), NULL); +NET_BUF_POOL_DEFINE(zoap_data_pool, 4, ZOAP_BUF_SIZE, 0, NULL); + +static const char *const test_path[] = { "test", NULL }; + +static struct in6_addr mcast_addr = MCAST_IP_ADDR; + +struct dtls_timing_context { + uint32_t snapshot; + uint32_t int_ms; + uint32_t fin_ms; +}; + +static void msg_dump(const char *s, uint8_t *data, unsigned int len) +{ + unsigned int i; + + printk("%s: ", s); + for (i = 0; i < len; i++) { + printk("%02x ", data[i]); + } + + printk("(%u bytes)\n", len); +} + +static int resource_reply_cb(const struct zoap_packet *response, + struct zoap_reply *reply, + const struct sockaddr *from) +{ + + struct net_buf *frag = response->buf->frags; + + while (frag) { + msg_dump("reply", frag->data, frag->len); + frag = frag->frags; + } + + return 0; +} + +static void my_debug(void *ctx, int level, + const char *file, int line, const char *str) +{ + const char *p, *basename; + + /* Extract basename from file */ + for (p = basename = file; *p != '\0'; p++) { + if (*p == '/' || *p == '\\') { + basename = p + 1; + } + } + + mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); +} + +void dtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms) +{ + struct dtls_timing_context *ctx = (struct dtls_timing_context *)data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if (fin_ms != 0) { + ctx->snapshot = k_uptime_get_32(); + } +} + +int dtls_timing_get_delay(void *data) +{ + struct dtls_timing_context *ctx = (struct dtls_timing_context *)data; + unsigned long elapsed_ms; + + if (ctx->fin_ms == 0) { + return -1; + } + + elapsed_ms = k_uptime_get_32() - ctx->snapshot; + + if (elapsed_ms >= ctx->fin_ms) { + return 2; + } + + if (elapsed_ms >= ctx->int_ms) { + return 1; + } + + return 0; +} + +static int entropy_source(void *data, unsigned char *output, size_t len, + size_t *olen) +{ + uint32_t seed; + char *ptr = data; + + seed = sys_rand32_get(); + + if (!seed) { + seed = 7; + } + + for (int i = 0; i < len; i++) { + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + *ptr++ = (char)seed; + } + + *olen = len; + return 0; +} + +void dtls_client(void) +{ + int ret; + struct udp_context ctx; + struct dtls_timing_context timer; + struct zoap_packet request, pkt; + struct zoap_reply *reply; + struct net_buf *nbuf, *frag; + uint8_t observe = 0; + const char *const *p; + uint16_t len; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_platform_set_printf(printk); + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + mbedtls_entropy_init(&entropy); + mbedtls_entropy_add_source(&entropy, entropy_source, NULL, + MBEDTLS_ENTROPY_MAX_GATHER, + MBEDTLS_ENTROPY_SOURCE_STRONG); + + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (ret != 0) { + mbedtls_printf("mbedtls_ctr_drbg_seed failed returned -0x%x\n", + -ret); + goto exit; + } + + ret = mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_DATAGRAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if (ret != 0) { + mbedtls_printf("mbedtls_ssl_config_defaults" + " failed! returned -0x%x\n", -ret); + goto exit; + } + +/* Modify this to change the default timeouts for the DTLS handshake */ +/* mbedtls_ssl_conf_handshake_timeout( &conf, min, max ); */ + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold(DEBUG_THRESHOLD); +#endif + + mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); + mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_init(heap, sizeof(heap)); +#endif + + ret = mbedtls_ssl_setup(&ssl, &conf); + + if (ret != 0) { + mbedtls_printf("mbedtls_ssl_setup failed returned -0x%x\n", + -ret); + goto exit; + } + + ret = udp_init(&ctx); + if (ret != 0) { + mbedtls_printf("udp_init failed returned 0x%x\n", ret); + goto exit; + } + + udp_tx(&ctx, payload, 32); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + ret = mbedtls_ssl_conf_psk(&conf, psk, strlen(psk), psk_id, + strlen(psk_id)); + if (ret != 0) { + mbedtls_printf(" failed\n mbedtls_ssl_conf_psk" + " returned -0x%x\n", -ret); + goto exit; + } +#endif + + mbedtls_ssl_set_timer_cb(&ssl, &timer, dtls_timing_set_delay, + dtls_timing_get_delay); + + mbedtls_ssl_set_bio(&ssl, &ctx, udp_tx, NULL, udp_rx); + + do { + ret = mbedtls_ssl_handshake(&ssl); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (ret != 0) { + mbedtls_printf("mbedtls_ssl_handshake failed returned -0x%x\n", + -ret); + goto exit; + } + + /* Write to server */ +retry: + nbuf = net_buf_alloc(&zoap_nbuf_pool, K_NO_WAIT); + if (!nbuf) { + goto exit; + } + + frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); + if (!frag) { + goto exit; + } + + net_buf_frag_add(nbuf, frag); + + ret = zoap_packet_init(&request, nbuf); + if (ret < 0) { + goto exit; + } + + zoap_header_set_version(&request, 1); + zoap_header_set_type(&request, ZOAP_TYPE_CON); + zoap_header_set_code(&request, ZOAP_METHOD_GET); + zoap_header_set_id(&request, zoap_next_id()); + zoap_header_set_token(&request, zoap_next_token(), 0); + + /* Enable observing the resource. */ + ret = zoap_add_option(&request, ZOAP_OPTION_OBSERVE, + &observe, sizeof(observe)); + if (ret < 0) { + mbedtls_printf("Unable add option to request.\n"); + goto exit; + } + + for (p = test_path; p && *p; p++) { + ret = zoap_add_option(&request, ZOAP_OPTION_URI_PATH, + *p, strlen(*p)); + if (ret < 0) { + mbedtls_printf("Unable add option/path to request.\n"); + goto exit; + } + } + + reply = zoap_reply_next_unused(replies, NUM_REPLIES); + if (!reply) { + mbedtls_printf("No resources for waiting for replies.\n"); + goto exit; + } + + zoap_reply_init(reply, &request); + reply->reply = resource_reply_cb; + len = frag->len; + + do { + ret = mbedtls_ssl_write(&ssl, frag->data, len); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + net_buf_unref(nbuf); + + if (ret <= 0) { + mbedtls_printf("mbedtls_ssl_write failed returned 0x%x\n", + -ret); + goto exit; + } + + nbuf = net_buf_alloc(&zoap_nbuf_pool, K_NO_WAIT); + if (!nbuf) { + mbedtls_printf("Could not get buffer from pool\n"); + goto exit; + } + + frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); + if (!frag) { + mbedtls_printf("Could not get frag from pool\n"); + goto exit; + } + + net_buf_frag_add(nbuf, frag); + len = ZOAP_BUF_SIZE - 1; + memset(frag->data, 0, ZOAP_BUF_SIZE); + + do { + ret = mbedtls_ssl_read(&ssl, frag->data, ZOAP_BUF_SIZE - 1); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (ret <= 0) { + net_buf_unref(nbuf); + + switch (ret) { + case MBEDTLS_ERR_SSL_TIMEOUT: + mbedtls_printf(" timeout\n"); + goto retry; + + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf(" connection was closed" + " gracefully\n"); + goto exit; + + default: + mbedtls_printf(" mbedtls_ssl_read" + " returned -0x%x\n", -ret); + goto exit; + } + } + + len = ret; + frag->len = len; + + ret = zoap_packet_parse(&pkt, nbuf); + if (ret) { + mbedtls_printf("Could not parse packet\n"); + goto exit; + } + + reply = zoap_response_received(&pkt, NULL, replies, NUM_REPLIES); + if (!reply) { + mbedtls_printf("No handler for response (%d)\n", ret); + } + + net_buf_unref(nbuf); + mbedtls_ssl_close_notify(&ssl); +exit: + + mbedtls_ssl_free(&ssl); + mbedtls_ssl_config_free(&conf); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); +} + +#define STACK_SIZE 4096 +uint8_t stack[STACK_SIZE]; + +static inline int init_app(void) +{ +#if defined(CONFIG_NET_SAMPLES_MY_IPV6_ADDR) + if (net_addr_pton(AF_INET6, + CONFIG_NET_SAMPLES_MY_IPV6_ADDR, + (struct sockaddr *)&client_addr) < 0) { + mbedtls_printf("Invalid IPv6 address %s", + CONFIG_NET_SAMPLES_MY_IPV6_ADDR); + } +#endif + if (!net_if_ipv6_addr_add(net_if_get_default(), &client_addr, + NET_ADDR_MANUAL, 0)) { + return -EIO; + } + + net_if_ipv6_maddr_add(net_if_get_default(), &mcast_addr); + + return 0; +} + +void main(void) +{ + if (init_app() != 0) { + printk("Cannot initialize network\n"); + return; + } + + k_thread_spawn(stack, STACK_SIZE, (k_thread_entry_t) dtls_client, + NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0); +} diff --git a/samples/net/coaps_client/src/udp.c b/samples/net/coaps_client/src/udp.c new file mode 100644 index 000000000..2663c79a0 --- /dev/null +++ b/samples/net/coaps_client/src/udp.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include <zephyr.h> +#include <net/net_core.h> +#include <net/net_context.h> +#include <net/nbuf.h> +#include <net/net_if.h> +#include <string.h> +#include <errno.h> +#include <misc/printk.h> + +#if !defined(CONFIG_MBEDTLS_CFG_FILE) +#include "mbedtls/config.h" +#else +#include CONFIG_MBEDTLS_CFG_FILE +#endif +#include "mbedtls/ssl.h" + +#include "udp_cfg.h" +#include "udp.h" + +static struct in6_addr server_addr; +static struct in6_addr mcast_addr = MCAST_IP_ADDR; +static const socklen_t addrlen = sizeof(struct sockaddr_in6); + +static void set_destination(struct sockaddr *addr) +{ + struct sockaddr_in6 *dst_addr = (struct sockaddr_in6 *)addr; + + net_ipaddr_copy(&dst_addr->sin6_addr, &server_addr); + dst_addr->sin6_family = AF_INET6; + dst_addr->sin6_port = htons(SERVER_PORT); +} + +static void udp_received(struct net_context *context, + struct net_buf *buf, int status, void *user_data) +{ + struct udp_context *ctx = user_data; + + ARG_UNUSED(context); + ARG_UNUSED(status); + + ctx->rx_nbuf = buf; + k_sem_give(&ctx->rx_sem); +} + +int udp_tx(void *context, const unsigned char *buf, size_t size) +{ + struct udp_context *ctx = context; + struct net_context *udp_ctx; + struct net_buf *send_buf; + struct sockaddr dst_addr; + int rc, len; + + udp_ctx = ctx->net_ctx; + + send_buf = net_nbuf_get_tx(udp_ctx); + if (!send_buf) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + rc = net_nbuf_append(send_buf, size, (uint8_t *) buf); + if (!rc) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + set_destination(&dst_addr); + len = net_buf_frags_len(send_buf); + k_sleep(UDP_TX_TIMEOUT); + + rc = net_context_sendto(send_buf, &dst_addr, + addrlen, NULL, K_FOREVER, NULL, NULL); + if (rc < 0) { + net_nbuf_unref(send_buf); + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } else { + return len; + } +} + +int udp_rx(void *context, unsigned char *buf, size_t size, uint32_t timeout) +{ + struct udp_context *ctx = context; + struct net_buf *rx_buf = NULL; + uint16_t read_bytes; + uint8_t *ptr; + int pos; + int len; + int rc; + + rc = k_sem_take(&ctx->rx_sem, timeout == 0 ? K_FOREVER : timeout); + if (rc != 0) { + return MBEDTLS_ERR_SSL_TIMEOUT; + } + + read_bytes = net_nbuf_appdatalen(ctx->rx_nbuf); + if (read_bytes > size) { + return MBEDTLS_ERR_SSL_ALLOC_FAILED; + } + + ptr = net_nbuf_appdata(ctx->rx_nbuf); + rx_buf = ctx->rx_nbuf->frags; + len = rx_buf->len - (ptr - rx_buf->data); + pos = 0; + + while (rx_buf) { + memcpy(buf + pos, ptr, len); + pos += len; + + rx_buf = rx_buf->frags; + if (!rx_buf) { + break; + } + + ptr = rx_buf->data; + len = rx_buf->len; + } + + net_nbuf_unref(ctx->rx_nbuf); + ctx->rx_nbuf = NULL; + + if (read_bytes != pos) { + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; + } + + rc = read_bytes; + ctx->remaining = 0; + + return rc; +} + +int udp_init(struct udp_context *ctx) +{ + struct net_context *udp_ctx = { 0 }; + struct net_context *mcast_ctx = { 0 }; + struct sockaddr_in6 my_addr = { 0 }; + struct sockaddr_in6 my_mcast_addr = { 0 }; + int rc; + + k_sem_init(&ctx->rx_sem, 0, UINT_MAX); + + net_ipaddr_copy(&my_mcast_addr.sin6_addr, &mcast_addr); + my_mcast_addr.sin6_family = AF_INET6; + + net_ipaddr_copy(&my_addr.sin6_addr, &client_addr); + my_addr.sin6_family = AF_INET6; + my_addr.sin6_port = htons(CLIENT_PORT); + + rc = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &udp_ctx); + if (rc < 0) { + printk("Cannot get network context for IPv6 UDP (%d)", rc); + return -EIO; + } + + rc = net_context_bind(udp_ctx, (struct sockaddr *)&my_addr, + sizeof(struct sockaddr_in6)); + if (rc < 0) { + printk("Cannot bind IPv6 UDP port %d (%d)", CLIENT_PORT, rc); + goto error; + } + + rc = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &mcast_ctx); + if (rc < 0) { + printk("Cannot get receiving IPv6 mcast (%d)", rc); + goto error; + } + + rc = net_context_bind(mcast_ctx, (struct sockaddr *)&my_mcast_addr, + sizeof(struct sockaddr_in6)); + if (rc < 0) { + printk("Cannot get bind IPv6 mcast (%d)", rc); + goto error; + } + + ctx->rx_nbuf = NULL; + ctx->remaining = 0; + ctx->net_ctx = udp_ctx; + +#if defined(CONFIG_NET_SAMPLES_PEER_IPV6_ADDR) + if (net_addr_pton(AF_INET6, + CONFIG_NET_SAMPLES_PEER_IPV6_ADDR, + (struct sockaddr *)&server_addr) < 0) { + printk("Invalid peer IPv6 address %s", + CONFIG_NET_SAMPLES_PEER_IPV6_ADDR); + } +#endif + + rc = net_context_recv(ctx->net_ctx, udp_received, K_NO_WAIT, ctx); + if (rc != 0) { + return -EIO; + } + + return 0; + +error: + net_context_put(udp_ctx); + return -EINVAL; +} diff --git a/samples/net/coaps_client/src/udp.h b/samples/net/coaps_client/src/udp.h new file mode 100644 index 000000000..7d96b3045 --- /dev/null +++ b/samples/net/coaps_client/src/udp.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _UDP_H_ +#define _UDP_H_ + +#include <net/net_core.h> + +struct udp_context { + struct net_context *net_ctx; + struct net_buf *rx_nbuf; + struct k_sem rx_sem; + int remaining; +}; + +int udp_init(struct udp_context *ctx); +int udp_tx(void *ctx, const unsigned char *buf, size_t size); +int udp_rx(void *ctx, unsigned char *buf, size_t size, uint32_t timeout); + +#endif diff --git a/samples/net/coaps_client/src/udp_cfg.h b/samples/net/coaps_client/src/udp_cfg.h new file mode 100644 index 000000000..d6cc6b6c6 --- /dev/null +++ b/samples/net/coaps_client/src/udp_cfg.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef UDP_CONFIG_H_ +#define UDP_CONFIG_H_ + +/* admin-local, dynamically allocated multicast address */ +#define MCAST_IP_ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0x2 } } } + +static struct in6_addr client_addr; + +#define SERVER_PORT 5684 +#define CLIENT_PORT 8484 + +#define UDP_TX_TIMEOUT 100 /* Timeout in milliseconds */ + +#endif diff --git a/samples/net/coaps_client/testcase.ini b/samples/net/coaps_client/testcase.ini new file mode 100644 index 000000000..bd398cafe --- /dev/null +++ b/samples/net/coaps_client/testcase.ini @@ -0,0 +1,4 @@ +[test] +tags = net +build_only = true +arch_whitelist = qemu_x86 arduino_101 diff --git a/samples/net/coaps_server/Makefile b/samples/net/coaps_server/Makefile new file mode 100644 index 000000000..d9ea788a2 --- /dev/null +++ b/samples/net/coaps_server/Makefile @@ -0,0 +1,14 @@ +# Makefile - CoAP over DTLS server test application + +# +# Copyright (c) 2015 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +BOARD ?= qemu_x86 +CONF_FILE ?= prj_$(BOARD).conf + +include $(ZEPHYR_BASE)/Makefile.inc + +include $(ZEPHYR_BASE)/samples/net/common/Makefile.ipstack diff --git a/samples/net/coaps_server/README.rst b/samples/net/coaps_server/README.rst new file mode 100644 index 000000000..23fa2a2d6 --- /dev/null +++ b/samples/net/coaps_server/README.rst @@ -0,0 +1,76 @@ +CoAP over DTLS sample server +############################ + +Overview +======== +This sample code shows a CoAP over DTLS server using mbedTLS on top of Zephyr. + +Building and Running +==================== + +Follow the steps for testing :ref:`networking with Qemu <networking_with_qemu>`. + +In the application directory type: + +.. code-block:: console + + $make run + +In other terminal window, obtain the libcoap code from: + +.. code-block:: console + + git clone --recursive -b dtls https://github.com/obgm/libcoap.git + +and put it in a well known directory, in your Linux machine, this will be your +client. In order to compile libcoap you may need to install the following +libraries, for Ubuntu + +.. code-block:: console + + sudo apt-get install libtool asciidoc + +Move to that directory and compile the libcoap on your host machine + +.. code-block:: console + + ./autogen.sh + ./configure --disable-shared + make all + +Now you can run the client like + +.. code-block:: console + + cd examples + ./coap-client -m get coaps://[2001:db8::1]/test -u Client_identity -k passwd + +You will get the following output: + +.. code-block:: console + + v:1 t:CON c:GET i:7154 {} [ ] + decrypt_verify(): found 24 bytes cleartext + decrypt_verify(): found 123 bytes cleartext + Type: 0 + Code: 1 + MID: 29012 + +From the app directory type the screen should display + +.. code-block:: console + + ******* + type: 0 code 1 id 29012 + ******* + mbedtls_ssl_read returned -0x7780 + +If the server does not receive the messages, restart the app and try to connect +the client again. + +References +========== + +* https://wiki.zephyrproject.org/view/Networking-with-Qemu +* https://tls.mbed.org/ +* https://libcoap.net/ diff --git a/samples/net/coaps_server/prj_qemu_x86.conf b/samples/net/coaps_server/prj_qemu_x86.conf new file mode 100644 index 000000000..9f157ce9c --- /dev/null +++ b/samples/net/coaps_server/prj_qemu_x86.conf @@ -0,0 +1,30 @@ +CONFIG_NETWORKING=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV4=y +CONFIG_NET_UDP=y +CONFIG_NET_TCP=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_LOG=y +CONFIG_NET_SLIP_TAP=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_INIT_STACKS=y +CONFIG_PRINTK=y +CONFIG_NET_STATISTICS=y +CONFIG_NET_NBUF_RX_COUNT=14 +CONFIG_NET_NBUF_TX_COUNT=14 +CONFIG_NET_NBUF_DATA_COUNT=30 +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2 +CONFIG_NET_MAX_CONTEXTS=10 + +CONFIG_ZOAP=y + +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_CFG_FILE="config-coap.h" + +CONFIG_NET_SAMPLES_IP_ADDRESSES=y +CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2" +CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.2" diff --git a/samples/net/coaps_server/src/Makefile b/samples/net/coaps_server/src/Makefile new file mode 100644 index 000000000..cd0b38fc0 --- /dev/null +++ b/samples/net/coaps_server/src/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (c) 2016 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +obj-y += coaps_server.o udp.o diff --git a/samples/net/coaps_server/src/coaps_server.c b/samples/net/coaps_server/src/coaps_server.c new file mode 100644 index 000000000..5efd97a0c --- /dev/null +++ b/samples/net/coaps_server/src/coaps_server.c @@ -0,0 +1,685 @@ +/* CoAP over DTLS server implemented with mbedTLS. + * (Meant to be used with config-coap.h) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * + * SPDX-License-Identifier: Apache-2.0 + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#include <zephyr.h> +#include <stdio.h> + +#include <errno.h> +#include <misc/printk.h> +#include <misc/byteorder.h> + +#if !defined(CONFIG_MBEDTLS_CFG_FILE) +#include "mbedtls/config.h" +#else +#include CONFIG_MBEDTLS_CFG_FILE +#endif + +#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 + +#include <string.h> +#include <net/net_context.h> +#include <net/net_if.h> +#include <net/buf.h> +#include <net/nbuf.h> +#include <net/net_ip.h> + +#include <net/zoap.h> + +#include "udp.h" +#include "udp_cfg.h" + +#include "mbedtls/net.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/ssl_cookie.h" + +#if defined(MBEDTLS_DEBUG_C) +#include "mbedtls/debug.h" +#define DEBUG_THRESHOLD 0 +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" +static unsigned char heap[8192]; +#endif + +#define ZOAP_BUF_SIZE 128 + +NET_BUF_POOL_DEFINE(zoap_nbuf_pool, 4, 0, sizeof(struct net_nbuf), NULL); +NET_BUF_POOL_DEFINE(zoap_data_pool, 4, ZOAP_BUF_SIZE, 0, NULL); + +/* + * Hardcoded values for server host and port + */ + +const char *pers = "dtsl_server"; + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +const unsigned char psk[] = "passwd\0"; +const char psk_id[] = "Client_identity\0"; +#endif + +static mbedtls_ssl_context *curr_ctx; + +static int send_response(struct zoap_packet *request, uint8_t response_code) +{ + struct net_buf *buf, *frag; + struct zoap_packet response; + uint8_t code, type, *payload; + uint16_t id, len; + int r; + + payload = zoap_packet_get_payload(request, &len); + if (!payload) { + printk("Packet without payload\n"); + return -EINVAL; + } + + code = zoap_header_get_code(request); + type = zoap_header_get_type(request); + id = zoap_header_get_id(request); + + printk("*******\n"); + printk("type: %u code %u id %u\n", type, code, id); + printk("*******\n"); + + buf = net_buf_alloc(&zoap_nbuf_pool, K_NO_WAIT); + if (!buf) { + return -ENOMEM; + } + + frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); + if (!frag) { + return -ENOMEM; + } + + net_buf_frag_add(buf, frag); + + r = zoap_packet_init(&response, buf); + if (r < 0) { + return -EINVAL; + } + + zoap_header_set_version(&response, 1); + zoap_header_set_type(&response, ZOAP_TYPE_ACK); + zoap_header_set_code(&response, response_code); + zoap_header_set_id(&response, id); + + do { + r = mbedtls_ssl_write(curr_ctx, frag->data, len); + } while (r == MBEDTLS_ERR_SSL_WANT_READ + || r == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (r >= 0) { + r = 0; + } + + net_buf_unref(buf); + + return r; +} + +static int test_del(struct zoap_resource *resource, + struct zoap_packet *request, const struct sockaddr *from) +{ + return send_response(request, ZOAP_RESPONSE_CODE_DELETED); +} + +static int test_put(struct zoap_resource *resource, + struct zoap_packet *request, const struct sockaddr *from) +{ + return send_response(request, ZOAP_RESPONSE_CODE_CHANGED); +} + +static int test_post(struct zoap_resource *resource, + struct zoap_packet *request, const struct sockaddr *from) +{ + return send_response(request, ZOAP_RESPONSE_CODE_CREATED); +} + +static int piggyback_get(struct zoap_resource *resource, + struct zoap_packet *request, + const struct sockaddr *from) +{ + struct net_buf *buf, *frag; + struct zoap_packet response; + uint8_t *payload, code, type; + uint16_t len, id; + int r; + + payload = zoap_packet_get_payload(request, &len); + if (!payload) { + printk("Packet without payload\n"); + return -EINVAL; + } + + code = zoap_header_get_code(request); + type = zoap_header_get_type(request); + id = zoap_header_get_id(request); + + printk("*******\n"); + printk("type: %u code %u id %u\n", type, code, id); + printk("*******\n"); + + buf = net_buf_alloc(&zoap_nbuf_pool, K_NO_WAIT); + if (!buf) { + return -ENOMEM; + } + + frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); + if (!frag) { + return -ENOMEM; + } + + net_buf_frag_add(buf, frag); + + r = zoap_packet_init(&response, buf); + if (r < 0) { + return -EINVAL; + } + + zoap_header_set_version(&response, 1); + zoap_header_set_type(&response, ZOAP_TYPE_ACK); + zoap_header_set_code(&response, ZOAP_RESPONSE_CODE_CONTENT); + zoap_header_set_id(&response, id); + + payload = zoap_packet_get_payload(&response, &len); + if (!payload) { + return -EINVAL; + } + + /* The response that coap-client expects */ + r = snprintk((char *)payload, len, "Type: %u\nCode: %u\nMID: %u\n", + type, code, id); + if (r < 0 || r > len) { + return -EINVAL; + } + + r = zoap_packet_set_used(&response, r); + if (r) { + return -EINVAL; + } + + do { + r = mbedtls_ssl_write(curr_ctx, frag->data, len); + } while (r == MBEDTLS_ERR_SSL_WANT_READ + || r == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (r >= 0) { + r = 0; + } + + net_buf_unref(buf); + + return r; +} + +static int query_get(struct zoap_resource *resource, + struct zoap_packet *request, const struct sockaddr *from) +{ + struct zoap_option options[4]; + struct net_buf *buf, *frag; + struct zoap_packet response; + uint8_t *payload, code, type; + uint16_t len, id; + int i, r; + + payload = zoap_packet_get_payload(request, &len); + if (!payload) { + printk("packet without payload\n"); + return -EINVAL; + } + + code = zoap_header_get_code(request); + type = zoap_header_get_type(request); + id = zoap_header_get_id(request); + + r = zoap_find_options(request, ZOAP_OPTION_URI_QUERY, options, 4); + if (r <= 0) { + return -EINVAL; + } + + printk("*******\n"); + printk("type: %u code %u id %u\n", type, code, id); + printk("num queries: %d\n", r); + + for (i = 0; i < r; i++) { + char str[16]; + + if (options[i].len + 1 > sizeof(str)) { + printk("Unexpected length of query: " + "%d (expected %zu)\n", + options[i].len, sizeof(str)); + break; + } + + memcpy(str, options[i].value, options[i].len); + str[options[i].len] = '\0'; + + printk("query[%d]: %s\n", i + 1, str); + } + + printk("*******\n"); + + buf = net_buf_alloc(&zoap_nbuf_pool, K_NO_WAIT); + if (!buf) { + return -ENOMEM; + } + + frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); + if (!frag) { + return -ENOMEM; + } + + net_buf_frag_add(buf, frag); + + r = zoap_packet_init(&response, buf); + if (r < 0) { + return -EINVAL; + } + + /* FIXME: Could be that zoap_packet_init() sets some defaults */ + zoap_header_set_version(&response, 1); + zoap_header_set_type(&response, ZOAP_TYPE_ACK); + zoap_header_set_code(&response, ZOAP_RESPONSE_CODE_CONTENT); + zoap_header_set_id(&response, id); + + payload = zoap_packet_get_payload(&response, &len); + if (!payload) { + return -EINVAL; + } + + /* The response that coap-client expects */ + r = snprintk((char *)payload, len, "Type: %u\nCode: %u\nMID: %u\n", + type, code, id); + if (r < 0 || r > len) { + return -EINVAL; + } + + r = zoap_packet_set_used(&response, r); + if (r) { + return -EINVAL; + } + + do { + r = mbedtls_ssl_write(curr_ctx, frag->data, len); + } while (r == MBEDTLS_ERR_SSL_WANT_READ + || r == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (r >= 0) { + r = 0; + } + + net_buf_unref(buf); + + return r; +} + +static const char *const test_path[] = { "test", NULL }; + +static const char *const segments_path[] = { "seg1", "seg2", "seg3", NULL }; + +static const char *const query_path[] = { "query", NULL }; + +static struct zoap_resource resources[] = { + {.get = piggyback_get, + .post = test_post, + .del = test_del, + .put = test_put, + .path = test_path}, + {.get = piggyback_get, + .path = segments_path, + }, + {.get = query_get, + .path = query_path, + }, + {}, +}; + +struct dtls_timing_context { + uint32_t snapshot; + uint32_t int_ms; + uint32_t fin_ms; +}; + +static void my_debug(void *ctx, int level, + const char *file, int line, const char *str) +{ + const char *p, *basename; + + ARG_UNUSED(ctx); + + /* Extract basename from file */ + for (p = basename = file; *p != '\0'; p++) { + if (*p == '/' || *p == '\\') { + basename = p + 1; + } + + } + + mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); +} + +void dtls_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms) +{ + struct dtls_timing_context *ctx = (struct dtls_timing_context *)data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if (fin_ms != 0) { + ctx->snapshot = k_uptime_get_32(); + } +} + +int dtls_timing_get_delay(void *data) +{ + struct dtls_timing_context *ctx = (struct dtls_timing_context *)data; + unsigned long elapsed_ms; + + if (ctx->fin_ms == 0) { + return -1; + } + + elapsed_ms = k_uptime_get_32() - ctx->snapshot; + + if (elapsed_ms >= ctx->fin_ms) { + return 2; + } + + if (elapsed_ms >= ctx->int_ms) { + return 1; + } + + return 0; +} + +static int entropy_source(void *data, unsigned char *output, size_t len, + size_t *olen) +{ + uint32_t seed; + char *ptr = data; + + ARG_UNUSED(data); + + seed = sys_rand32_get(); + + if (!seed) { + seed = 7; + } + + for (size_t i = 0; i < len; i++) { + seed ^= seed << 13; + seed ^= seed >> 17; + seed ^= seed << 5; + *ptr++ = (char)seed; + } + + *olen = len; + return 0; +} + +void dtls_server(void) +{ + int len, ret = 0; + struct udp_context ctx; + struct dtls_timing_context timer; + struct zoap_packet pkt; + struct net_buf *nbuf, *frag; + + mbedtls_ssl_cookie_ctx cookie_ctx; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + + mbedtls_ctr_drbg_init(&ctr_drbg); + + mbedtls_platform_set_printf(printk); + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold(DEBUG_THRESHOLD); +#endif + + /* + * Initialize and setup + */ + mbedtls_ssl_init(&ssl); + mbedtls_ssl_config_init(&conf); + + mbedtls_entropy_init(&entropy); + mbedtls_entropy_add_source(&entropy, entropy_source, NULL, + MBEDTLS_ENTROPY_MAX_GATHER, + MBEDTLS_ENTROPY_SOURCE_STRONG); + + ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (ret != 0) { + mbedtls_printf(" failed!\n" + " mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); + goto exit; + } + + ret = mbedtls_ssl_config_defaults(&conf, + MBEDTLS_SSL_IS_SERVER, + MBEDTLS_SSL_TRANSPORT_DATAGRAM, + MBEDTLS_SSL_PRESET_DEFAULT); + if (ret != 0) { + mbedtls_printf(" failed!\n" + " mbedtls_ssl_config_defaults returned -0x%x\n", + -ret); + goto exit; + } + +/* Modify this to change the default timeouts for the DTLS handshake */ +/* mbedtls_ssl_conf_handshake_timeout( &conf, min, max ); */ + + mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); + mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_init(heap, sizeof(heap)); +#endif + ret = mbedtls_ssl_cookie_setup(&cookie_ctx, mbedtls_ctr_drbg_random, + &ctr_drbg); + if (ret != 0) { + mbedtls_printf(" failed!\n" + " mbedtls_ssl_cookie_setup returned -0x%x\n", + -ret); + goto exit; + } + + mbedtls_ssl_conf_dtls_cookies(&conf, mbedtls_ssl_cookie_write, + mbedtls_ssl_cookie_check, &cookie_ctx); + + ret = mbedtls_ssl_setup(&ssl, &conf); + if (ret != 0) { + mbedtls_printf(" failed!\n" + " mbedtls_ssl_setup returned -0x%x\n", -ret); + goto exit; + } + + ret = udp_init(&ctx); + if (ret != 0) { + mbedtls_printf(" failed!\n udp_init returned 0x%x\n", ret); + goto exit; + } + +reset: + mbedtls_ssl_session_reset(&ssl); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + ret = + mbedtls_ssl_conf_psk(&conf, psk, strlen(psk), psk_id, + strlen(psk_id)); + if (ret != 0) { + mbedtls_printf(" failed!\n mbedtls_ssl_conf_psk" + " returned -0x%04X\n", -ret); + goto exit; + } +#endif + + mbedtls_ssl_set_timer_cb(&ssl, &timer, dtls_timing_set_delay, + dtls_timing_get_delay); + + mbedtls_ssl_set_bio(&ssl, &ctx, udp_tx, udp_rx, NULL); + + /* For HelloVerifyRequest cookies */ + ctx.client_id = (char)ctx.remaining; + + ret = mbedtls_ssl_set_client_transport_id(&ssl, &ctx.client_id, + sizeof(char)); + if (ret != 0) { + mbedtls_printf(" failed!\n" + " mbedtls_ssl_set_client_transport_id()" + " returned -0x%x\n", -ret); + goto exit; + } + + curr_ctx = &ssl; + + do { + ret = mbedtls_ssl_handshake(&ssl); + } while (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE); + + if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) { + ret = 0; + goto reset; + } + + if (ret != 0) { + mbedtls_printf(" failed!\n" + " mbedtls_ssl_handshake returned -0x%x\n", + -ret); + goto reset; + } + + do { + /* Read the request */ + nbuf = net_buf_alloc(&zoap_nbuf_pool, K_NO_WAIT); + if (!nbuf) { + mbedtls_printf("Could not get buffer from pool\n"); + goto exit; + } + + frag = net_buf_alloc(&zoap_data_pool, K_NO_WAIT); + if (!frag) { + mbedtls_printf("Could not get frag from pool\n"); + goto exit; + } + + net_buf_frag_add(nbuf, frag); + len = ZOAP_BUF_SIZE - 1; + memset(frag->data, 0, ZOAP_BUF_SIZE); + + ret = mbedtls_ssl_read(&ssl, frag->data, len); + if (ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE) { + continue; + } + + if (ret <= 0) { + net_buf_unref(nbuf); + + switch (ret) { + case MBEDTLS_ERR_SSL_TIMEOUT: + mbedtls_printf(" timeout\n"); + goto reset; + + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf(" connection was closed" + " gracefully\n"); + goto close_notify; + + default: + mbedtls_printf(" mbedtls_ssl_read" + " returned -0x%x\n", -ret); + goto reset; + } + } + + len = ret; + frag->len = len; + + ret = zoap_packet_parse(&pkt, nbuf); + if (ret) { + mbedtls_printf("Could not parse packet\n"); + goto exit; + } + + ret = zoap_handle_request(&pkt, resources, + (const struct sockaddr *)&ssl); + if (ret < 0) { + mbedtls_printf("No handler for such request (%d)\n", + ret); + } + + net_buf_unref(nbuf); + + } while (1); + +close_notify: + /* No error checking, the connection might be closed already */ + do { + ret = mbedtls_ssl_close_notify(&ssl); + } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); + ret = 0; + mbedtls_printf(" done\n"); + goto reset; + +exit: + mbedtls_ssl_free(&ssl); + mbedtls_ssl_config_free(&conf); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); +} + +#define STACK_SIZE 4096 +uint8_t stack[STACK_SIZE]; + +static inline int init_app(void) +{ +#if defined(CONFIG_NET_SAMPLES_MY_IPV6_ADDR) + if (net_addr_pton(AF_INET6, CONFIG_NET_SAMPLES_MY_IPV6_ADDR, + (struct sockaddr *)&server_addr) < 0) { + mbedtls_printf("Invalid IPv6 address %s", + CONFIG_NET_SAMPLES_MY_IPV6_ADDR); + } +#endif + if (!net_if_ipv6_addr_add(net_if_get_default(), &server_addr, + NET_ADDR_MANUAL, 0)) { + return -EIO; + } + + net_if_ipv6_maddr_add(net_if_get_default(), &mcast_addr); + + return 0; +} + +void main(void) +{ + if (init_app() != 0) { + printk("Cannot initialize network\n"); + return; + } + + k_thread_spawn(stack, STACK_SIZE, (k_thread_entry_t) dtls_server, + NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0); + +} diff --git a/samples/net/coaps_server/src/udp.c b/samples/net/coaps_server/src/udp.c new file mode 100644 index 000000000..f2a7081db --- /dev/null +++ b/samples/net/coaps_server/src/udp.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include <zephyr.h> +#include <net/net_core.h> +#include <net/net_context.h> +#include <net/nbuf.h> +#include <net/net_if.h> +#include <string.h> +#include <errno.h> +#include <misc/printk.h> + +#include "udp_cfg.h" +#include "udp.h" + +static const socklen_t addrlen = sizeof(struct sockaddr_in6); + +static void set_client_address(struct sockaddr *addr, struct net_buf *rx_buf) +{ + net_ipaddr_copy(&net_sin6(addr)->sin6_addr, &NET_IPV6_BUF(rx_buf)->src); + net_sin6(addr)->sin6_family = AF_INET6; + net_sin6(addr)->sin6_port = NET_UDP_BUF(rx_buf)->src_port; +} + +static void udp_received(struct net_context *context, + struct net_buf *buf, int status, void *user_data) +{ + struct udp_context *ctx = user_data; + + ARG_UNUSED(context); + ARG_UNUSED(status); + + ctx->rx_nbuf = buf; + k_sem_give(&ctx->rx_sem); +} + +int udp_tx(void *context, const unsigned char *buf, size_t size) +{ + struct udp_context *ctx = context; + struct net_context *net_ctx; + struct net_buf *send_buf; + + int rc, len; + + net_ctx = ctx->net_ctx; + + send_buf = net_nbuf_get_tx(net_ctx); + if (!send_buf) { + printk("cannot create buf\n"); + return -EIO; + } + + rc = net_nbuf_append(send_buf, size, (uint8_t *) buf); + if (!rc) { + printk("cannot write buf\n"); + return -EIO; + } + + len = net_buf_frags_len(send_buf); + + rc = net_context_sendto(send_buf, &net_ctx->remote, + addrlen, NULL, K_FOREVER, NULL, NULL); + + if (rc < 0) { + printk("Cannot send data to peer (%d)\n", rc); + net_nbuf_unref(send_buf); + return -EIO; + } else { + return len; + } +} + +int udp_rx(void *context, unsigned char *buf, size_t size) +{ + struct udp_context *ctx = context; + struct net_context *net_ctx = ctx->net_ctx; + struct net_buf *rx_buf = NULL; + uint16_t read_bytes; + uint8_t *ptr; + int pos; + int len; + int rc; + + k_sem_take(&ctx->rx_sem, K_FOREVER); + + read_bytes = net_nbuf_appdatalen(ctx->rx_nbuf); + if (read_bytes > size) { + return -ENOMEM; + } + + rx_buf = ctx->rx_nbuf; + + set_client_address(&net_ctx->remote, rx_buf); + + ptr = net_nbuf_appdata(rx_buf); + rx_buf = rx_buf->frags; + len = rx_buf->len - (ptr - rx_buf->data); + pos = 0; + + while (rx_buf) { + memcpy(buf + pos, ptr, len); + pos += len; + + rx_buf = rx_buf->frags; + if (!rx_buf) { + break; + } + + ptr = rx_buf->data; + len = rx_buf->len; + } + + net_nbuf_unref(ctx->rx_nbuf); + ctx->rx_nbuf = NULL; + + if (read_bytes != pos) { + return -EIO; + } + + rc = read_bytes; + ctx->remaining = 0; + + return rc; +} + +int udp_init(struct udp_context *ctx) +{ + struct net_context *udp_ctx = { 0 }; + struct net_context *mcast_ctx = { 0 }; + struct sockaddr_in6 my_addr = { 0 }; + struct sockaddr_in6 my_mcast_addr = { 0 }; + int rc; + + k_sem_init(&ctx->rx_sem, 0, UINT_MAX); + + net_ipaddr_copy(&my_mcast_addr.sin6_addr, &mcast_addr); + my_mcast_addr.sin6_family = AF_INET6; + + net_ipaddr_copy(&my_addr.sin6_addr, &server_addr); + my_addr.sin6_family = AF_INET6; + my_addr.sin6_port = htons(SERVER_PORT); + + rc = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &udp_ctx); + if (rc < 0) { + printk("Cannot get network context for IPv6 UDP (%d)", rc); + return -EIO; + } + + rc = net_context_bind(udp_ctx, (struct sockaddr *)&my_addr, + sizeof(struct sockaddr_in6)); + if (rc < 0) { + printk("Cannot bind IPv6 UDP port %d (%d)", SERVER_PORT, rc); + goto error; + } + + rc = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, &mcast_ctx); + if (rc < 0) { + printk("Cannot get receiving IPv6 mcast (%d)", rc); + goto error; + } + + rc = net_context_bind(mcast_ctx, (struct sockaddr *)&my_mcast_addr, + sizeof(struct sockaddr_in6)); + if (rc < 0) { + printk("Cannot get bind IPv6 mcast (%d)", rc); + goto error; + } + + ctx->rx_nbuf = NULL; + ctx->remaining = 0; + ctx->net_ctx = udp_ctx; + + rc = net_context_recv(ctx->net_ctx, udp_received, K_NO_WAIT, ctx); + if (rc != 0) { + return -EIO; + } + + return 0; + +error: + net_context_put(udp_ctx); + return -EINVAL; +} diff --git a/samples/net/coaps_server/src/udp.h b/samples/net/coaps_server/src/udp.h new file mode 100644 index 000000000..716dc5d67 --- /dev/null +++ b/samples/net/coaps_server/src/udp.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _UDP_H_ +#define _UDP_H_ + +#include <net/net_core.h> + +struct udp_context { + struct net_context *net_ctx; + struct net_buf *rx_nbuf; + struct k_sem rx_sem; + int remaining; + char client_id; +}; + +int udp_init(struct udp_context *ctx); +int udp_tx(void *ctx, const unsigned char *buf, size_t size); +int udp_rx(void *ctx, unsigned char *buf, size_t size); + +#endif diff --git a/samples/net/coaps_server/src/udp_cfg.h b/samples/net/coaps_server/src/udp_cfg.h new file mode 100644 index 000000000..ef6e39b1d --- /dev/null +++ b/samples/net/coaps_server/src/udp_cfg.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef UDP_CONFIG_H_ +#define UDP_CONFIG_H_ + +#define MCAST_IP_ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0x2 } } } + +#define SERVER_PREFIX_LEN 64 + +static struct in6_addr server_addr; +static struct in6_addr mcast_addr = MCAST_IP_ADDR; + +#define SERVER_PORT 5684 + +#endif diff --git a/samples/net/coaps_server/testcase.ini b/samples/net/coaps_server/testcase.ini new file mode 100644 index 000000000..2bde3d1a6 --- /dev/null +++ b/samples/net/coaps_server/testcase.ini @@ -0,0 +1,4 @@ +[test] +tags = net +build_only = true +arch_whitelist = qemu_x86 diff --git a/samples/net/dhcpv4_client/README.rst b/samples/net/dhcpv4_client/README.rst new file mode 100644 index 000000000..702b907b0 --- /dev/null +++ b/samples/net/dhcpv4_client/README.rst @@ -0,0 +1,161 @@ +Sample DHCPv4 client application +################################ + +Overview +******** + +This application starts a DHCPv4 client, gets an IPv4 address from the +DHCPv4 server, and prints address, lease time, netmask and router +information to a serial console. + +Requirements +************ + +- net_tools: + + https://wiki.zephyrproject.org/view/Networking-with-Qemu + +Building and Running +******************** + +QEMU x86 +======== + +These are instructions for how to use this sample application using +QEMU on a Linux host to negotiate IP address from DHCPv4 server running +on Linux host. + +Follow readme from: + + Run 'loop_socat' and 'loop-slip-tap' scripts from net-tools. + + https://gerrit.zephyrproject.org/r/gitweb?p=net-tools.git;a=blob;f=README + +.. code-block:: console + + $ ./loop_socat.sh + +In another window: + +.. code-block:: console + + $ sudo ./loop-slip-tap.sh + +Here's a sample server configuration file '/etc/dhcpd/dhcp.conf' +used to configure the DHCPv4 server: + +.. code-block:: console + + log-facility local7; + default-lease-time 600; + max-lease-time 7200; + + subnet 192.0.2.0 netmask 255.255.255.0 { + range 192.0.2.10 192.0.2.100; + } + +Use another terminal window to start up a DHCPv4 server on the Linux host, +using this conf file: + +.. code-block:: console + + $ sudo dhcpd -d -4 -cf /etc/dhcp/dhcpd.conf -lf /var/lib/dhcp/dhcpd.leases tap0 + +Run Zephyr samples/net/dhcpv4_client application in QEMU: + +.. code-block:: console + + $ cd $ZEPHYR_BASE/samples/net/dhcpv4_client + $ make pristine && make qemu + +Once DHCPv4 client address negotiation completed with server, details +are shown like this: + +.. code-block:: console + + [dhcpv4] [INF] main: In main + [dhcpv4] [INF] main_thread: Run dhcpv4 client + [dhcpv4] [INF] handler: Your address: 192.0.2.10 + [dhcpv4] [INF] handler: Lease time: 600 + [dhcpv4] [INF] handler: Subnet: 255.255.255.0 + [dhcpv4] [INF] handler: Router: 0.0.0.0 + +To verify the Zephyr application client is running and has received +an ip address by typing: + +.. code-block:: console + + $ ping -I tap0 192.0.2.10 + + +FRDM_K64F +========= + +These are instructions for how to use this sample application running in FRDM_K64F +board to negotiate IP address from DHCPv4 server running on Linux host. + +Instructions to follow building, flashing and observe serial console logs: + + https://wiki.zephyrproject.org/view/NXP_FRDM-K64F#Quick_Start + +Connect ethernet cable from frdm board to Linux host machine and check +for new interfaces: + +.. code-block:: console + + $ ifconfig + +Add ip address and routing information to interface: + +.. code-block:: console + + $ sudo ip addr add 192.0.2.2 dev eth1 + $ sudo ip route add 192.0.2.0/24 dev eth1 + +Here's a sample server configuration file '/etc/dhcpd/dhcp.conf' +used to configure the DHCPv4 server: + +.. code-block:: console + + log-facility local7; + default-lease-time 600; + max-lease-time 7200; + + subnet 192.0.2.0 netmask 255.255.255.0 { + range 192.0.2.10 192.0.2.100; + } + +Use another terminal window to start up a DHCPv4 server on the Linux host, +using this conf file: + +.. code-block:: console + + $ sudo dhcpd -d -4 -cf /etc/dhcp/dhcpd.conf -lf /var/lib/dhcp/dhcpd.leases eth1 + +Run Zephyr samples/net/dhcpv4_client application in QEMU: + +.. code-block:: console + + $ cd $ZEPHYR_BASE/samples/net/dhcpv4_client + $ make pristine && make BOARD=frdm_k64f + $ cp outdir/frdm_k64f/zephyr.bin /media/rveerama/MBED/ + +Once DHCPv4 client address negotiation completed with server, details +are shown like this: + +.. code-block:: console + + $ sudo screen /dev/ttyACM0 115200 + [dhcpv4] [INF] main: In main + [dhcpv4] [INF] main_thread: Run dhcpv4 client + [dhcpv4] [INF] handler: Your address: 192.0.2.10 + [dhcpv4] [INF] handler: Lease time: 600 + [dhcpv4] [INF] handler: Subnet: 255.255.255.0 + [dhcpv4] [INF] handler: Router: 0.0.0.0 + +To verify the Zephyr application client is running and has received +an ip address by typing: + +.. code-block:: console + + $ ping -I eth1 192.0.2.10 diff --git a/samples/net/dns_client/prj_qemu_x86.conf b/samples/net/dns_client/prj_qemu_x86.conf index f2f8e5721..96d98816e 100644 --- a/samples/net/dns_client/prj_qemu_x86.conf +++ b/samples/net/dns_client/prj_qemu_x86.conf @@ -4,7 +4,7 @@ CONFIG_NET_UDP=y CONFIG_RANDOM_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_NET_LOG=y -CONFIG_SLIP_TAP=y +CONFIG_NET_SLIP_TAP=y CONFIG_INIT_STACKS=y CONFIG_NET_NBUF_RX_COUNT=16 CONFIG_NET_NBUF_TX_COUNT=16 diff --git a/samples/net/echo_client/prj_frdm_k64f_mcr20a.conf b/samples/net/echo_client/prj_frdm_k64f_mcr20a.conf new file mode 100644 index 000000000..c5f2e455f --- /dev/null +++ b/samples/net/echo_client/prj_frdm_k64f_mcr20a.conf @@ -0,0 +1,48 @@ +CONFIG_NETWORKING=y + +CONFIG_NET_NBUF_RX_COUNT=20 +CONFIG_NET_NBUF_TX_COUNT=5 +CONFIG_NET_NBUF_DATA_COUNT=40 + +CONFIG_NET_IPV4=n +CONFIG_NET_IPV6=y +CONFIG_NET_IPV6_RA_RDNSS=y +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=2 + +CONFIG_NET_6LO=y +CONFIG_NET_DEBUG_6LO=n + +CONFIG_NET_LOG=y +CONFIG_SYS_LOG_NET_LEVEL=1 +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_INIT_STACKS=y +CONFIG_PRINTK=y + +CONFIG_NET_DEBUG_CORE=y +CONFIG_NET_DEBUG_IPV6_NBR_CACHE=y +CONFIG_NET_DEBUG_IPV6=y +CONFIG_NET_DEBUG_CONTEXT=y +CONFIG_NET_DEBUG_NET_BUF=n +CONFIG_NET_DEBUG_UTILS=n +CONFIG_NET_DEBUG_IF=n +CONFIG_NET_DEBUG_ICMPV6=y +CONFIG_NET_DEBUG_CONN=n +CONFIG_NET_STATISTICS=y +CONFIG_NET_STATISTICS_PERIODIC_OUTPUT=y + +CONFIG_NET_L2_IEEE802154=y +CONFIG_NET_DEBUG_L2_IEEE802154=y +CONFIG_NET_L2_IEEE802154_ORFD=y +CONFIG_NET_L2_IEEE802154_FRAGMENT=y +CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=n + +CONFIG_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_0=y + +CONFIG_NXP_MCR20A=y +CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1 + +CONFIG_NET_SAMPLES_IP_ADDRESSES=y +CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2" diff --git a/samples/net/echo_client/src/Makefile b/samples/net/echo_client/src/Makefile index ee1258478..8802055a5 100644 --- a/samples/net/echo_client/src/Makefile +++ b/samples/net/echo_client/src/Makefile @@ -1,5 +1,7 @@ obj-y = echo-client.o +ifeq ($(CONFIG_TI_CC2520),y) + ifeq ($(CONFIG_BOARD_ARDUINO_101),y) ccflags-y +=-I${ZEPHYR_BASE}/include/drivers/ obj-y += ../../common/cc2520_a101.o @@ -11,6 +13,8 @@ ccflags-y +=-I${ZEPHYR_BASE}/include/drivers/ obj-y += ../../common/cc2520_frdm_k64f.o endif +endif + ifeq ($(CONFIG_NET_TESTING), y) ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/ ccflags-y +=-DNET_TESTING_SERVER=0 diff --git a/samples/net/echo_client/src/echo-client.c b/samples/net/echo_client/src/echo-client.c index 86c6128db..f5aba7325 100644 --- a/samples/net/echo_client/src/echo-client.c +++ b/samples/net/echo_client/src/echo-client.c @@ -68,6 +68,32 @@ static char *lorem_ipsum = static int ipsum_len; +#define MY_PORT 8484 +#define PEER_PORT 4242 + +struct data { + uint32_t expecting_udp; + uint32_t expecting_tcp; + uint32_t received_tcp; +}; + +static struct { +#if defined(CONFIG_NET_UDP) + /* semaphore for controlling udp data sending */ + struct k_sem recv_ipv6; + struct k_sem recv_ipv4; +#endif /* CONFIG_NET_UDP */ + + struct data ipv4; + struct data ipv6; +} conf; + +#if defined(CONFIG_NET_TCP) +static bool send_tcp_data(struct net_context *ctx, + char *proto, + struct data *data); +#endif /* CONFIG_NET_TCP */ + #if defined(CONFIG_NET_IPV6) /* admin-local, dynamically allocated multicast address */ #define MCAST_IP6ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \ @@ -85,8 +111,22 @@ static int ipsum_len; static struct in6_addr in6addr_my = MY_IP6ADDR; static struct in6_addr in6addr_peer = PEER_IP6ADDR; static struct in6_addr in6addr_mcast = MCAST_IP6ADDR; -static struct k_sem recv_ipv6; -static int expecting_ipv6; + +static struct sockaddr_in6 my_addr6 = { + .sin6_family = AF_INET6, + .sin6_port = htons(MY_PORT), +}; + +static struct sockaddr_in6 peer_addr6 = { + .sin6_family = AF_INET6, + .sin6_port = htons(PEER_PORT), +}; + +static struct sockaddr_in6 mcast_addr6 = { + .sin6_family = AF_INET6, + .sin6_port = htons(PEER_PORT), +}; + static char __noinit __stack ipv6_stack[STACKSIZE]; #endif /* CONFIG_NET_IPV6 */ @@ -100,15 +140,21 @@ static char __noinit __stack ipv6_stack[STACKSIZE]; static struct in_addr in4addr_my = MY_IP4ADDR; static struct in_addr in4addr_peer = PEER_IP4ADDR; -static struct k_sem recv_ipv4; -static int expecting_ipv4; + +static struct sockaddr_in my_addr4 = { + .sin_family = AF_INET, + .sin_port = htons(MY_PORT), +}; + +static struct sockaddr_in peer_addr4 = { + .sin_family = AF_INET, + .sin_port = htons(PEER_PORT), +}; + static char __noinit __stack ipv4_stack[STACKSIZE]; #endif /* CONFIG_NET_IPV4 */ -#define MY_PORT 8484 -#define PEER_PORT 4242 - #define WAIT_TIME (2 * MSEC_PER_SEC) #if defined(CONFIG_NET_MGMT_EVENT) @@ -120,21 +166,25 @@ static inline void init_app(void) NET_INFO("Run echo client"); #if defined(CONFIG_NET_IPV6) -#if defined(CONFIG_NET_SAMPLES_MY_IPV6_ADDR) +#if defined(CONFIG_NET_SAMPLES_IP_ADDRESSES) if (net_addr_pton(AF_INET6, CONFIG_NET_SAMPLES_MY_IPV6_ADDR, - (struct sockaddr *)&in6addr_my) < 0) { + (struct sockaddr *)&my_addr6.sin6_addr) < 0) { NET_ERR("Invalid IPv6 address %s", CONFIG_NET_SAMPLES_MY_IPV6_ADDR); + + net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my); } #endif -#if defined(CONFIG_NET_SAMPLES_PEER_IPV6_ADDR) +#if defined(CONFIG_NET_SAMPLES_IP_ADDRESSES) if (net_addr_pton(AF_INET6, CONFIG_NET_SAMPLES_PEER_IPV6_ADDR, - (struct sockaddr *)&in6addr_peer) < 0) { + (struct sockaddr *)&peer_addr6.sin6_addr) < 0) { NET_ERR("Invalid peer IPv6 address %s", CONFIG_NET_SAMPLES_PEER_IPV6_ADDR); + + net_ipaddr_copy(&peer_addr6.sin6_addr, &in6addr_peer); } #endif @@ -142,74 +192,62 @@ static inline void init_app(void) struct net_if_addr *ifaddr; ifaddr = net_if_ipv6_addr_add(net_if_get_default(), - &in6addr_my, NET_ADDR_MANUAL, 0); + &my_addr6.sin6_addr, + NET_ADDR_MANUAL, 0); } while (0); + net_ipaddr_copy(&mcast_addr6.sin6_addr, &in6addr_mcast); net_if_ipv6_maddr_add(net_if_get_default(), &in6addr_mcast); - k_sem_init(&recv_ipv6, 0, UINT_MAX); +#if defined(CONFIG_NET_UDP) + k_sem_init(&conf.recv_ipv6, 0, UINT_MAX); +#endif #endif #if defined(CONFIG_NET_IPV4) #if defined(CONFIG_NET_DHCPV4) net_dhcpv4_start(net_if_get_default()); #else -#if defined(CONFIG_NET_SAMPLES_MY_IPV4_ADDR) +#if defined(CONFIG_NET_SAMPLES_IP_ADDRESSES) if (net_addr_pton(AF_INET, CONFIG_NET_SAMPLES_MY_IPV4_ADDR, - (struct sockaddr *)&in4addr_my) < 0) { + (struct sockaddr *)&my_addr4.sin_addr) < 0) { NET_ERR("Invalid IPv4 address %s", CONFIG_NET_SAMPLES_MY_IPV4_ADDR); + + net_ipaddr_copy(&my_addr4.sin_addr, &in4addr_my); } #endif -#if defined(CONFIG_NET_SAMPLES_PEER_IPV4_ADDR) +#if defined(CONFIG_NET_SAMPLES_IP_ADDRESSES) if (net_addr_pton(AF_INET, CONFIG_NET_SAMPLES_PEER_IPV4_ADDR, - (struct sockaddr *)&in4addr_peer) < 0) { + (struct sockaddr *)&peer_addr4.sin_addr) < 0) { NET_ERR("Invalid peer IPv4 address %s", CONFIG_NET_SAMPLES_PEER_IPV4_ADDR); + + net_ipaddr_copy(&peer_addr4.sin_addr, &in4addr_peer); } #endif - net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my, + net_if_ipv4_addr_add(net_if_get_default(), &my_addr4.sin_addr, NET_ADDR_MANUAL, 0); #endif /* CONFIG_NET_DHCPV4 */ - k_sem_init(&recv_ipv4, 0, UINT_MAX); +#if defined(CONFIG_NET_UDP) + k_sem_init(&conf.recv_ipv4, 0, UINT_MAX); +#endif #endif } static inline bool get_context(struct net_context **udp_recv4, struct net_context **udp_recv6, + struct net_context **tcp_recv4, + struct net_context **tcp_recv6, struct net_context **mcast_recv6) { int ret; -#if defined(CONFIG_NET_IPV6) - struct sockaddr_in6 mcast_addr6 = { 0 }; - struct sockaddr_in6 my_addr6 = { 0 }; -#endif - -#if defined(CONFIG_NET_IPV4) - struct sockaddr_in my_addr4 = { 0 }; -#endif - -#if defined(CONFIG_NET_IPV6) - net_ipaddr_copy(&mcast_addr6.sin6_addr, &in6addr_mcast); - mcast_addr6.sin6_family = AF_INET6; - - net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my); - my_addr6.sin6_family = AF_INET6; - my_addr6.sin6_port = htons(MY_PORT); -#endif - -#if defined(CONFIG_NET_IPV4) - net_ipaddr_copy(&my_addr4.sin_addr, &in4addr_my); - my_addr4.sin_family = AF_INET; - my_addr4.sin_port = htons(MY_PORT); -#endif - #if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP) ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6); if (ret < 0) { @@ -258,6 +296,47 @@ static inline bool get_context(struct net_context **udp_recv4, } #endif +#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP) + if (tcp_recv6) { + ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, + tcp_recv6); + if (ret < 0) { + NET_ERR("Cannot get network context " + "for IPv6 TCP (%d)", ret); + return false; + } + + ret = net_context_bind(*tcp_recv6, + (struct sockaddr *)&my_addr6, + sizeof(struct sockaddr_in6)); + if (ret < 0) { + NET_ERR("Cannot bind IPv6 TCP port %d (%d)", + ntohs(my_addr6.sin6_port), ret); + return false; + } + } +#endif + +#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP) + if (tcp_recv4) { + ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, + tcp_recv4); + if (ret < 0) { + NET_ERR("Cannot get network context for IPv4 TCP"); + return false; + } + + ret = net_context_bind(*tcp_recv4, + (struct sockaddr *)&my_addr4, + sizeof(struct sockaddr_in)); + if (ret < 0) { + NET_ERR("Cannot bind IPv4 TCP port %d", + ntohs(my_addr4.sin_port)); + return false; + } + } +#endif + return true; } @@ -320,7 +399,7 @@ static inline void set_dst_addr(sa_family_t family, #if defined(CONFIG_NET_IPV6) if (family == AF_INET6) { net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr, - &in6addr_peer); + &peer_addr6.sin6_addr); net_sin6(dst_addr)->sin6_family = AF_INET6; net_sin6(dst_addr)->sin6_port = htons(PEER_PORT); @@ -331,7 +410,7 @@ static inline void set_dst_addr(sa_family_t family, #if defined(CONFIG_NET_IPV4) if (family == AF_INET) { net_ipaddr_copy(&net_sin(dst_addr)->sin_addr, - &in4addr_peer); + &peer_addr4.sin_addr); net_sin(dst_addr)->sin_family = AF_INET; net_sin(dst_addr)->sin_port = htons(PEER_PORT); @@ -340,7 +419,8 @@ static inline void set_dst_addr(sa_family_t family, #endif /* CONFIG_NET_IPV4 */ } -static bool compare_data(struct net_buf *buf, int expecting_len) +#if defined(CONFIG_NET_UDP) +static bool compare_udp_data(struct net_buf *buf, int expecting_len) { uint8_t *ptr = net_nbuf_appdata(buf); int pos = 0; @@ -351,9 +431,9 @@ static bool compare_data(struct net_buf *buf, int expecting_len) */ buf = buf->frags; - /* Do not include the protocol headers in len for the - * first fragment. The remaining fragments contain only - * data so the user data length is directly the fragment len. + /* Do not include the protocol headers in the first fragment. + * The remaining fragments contain only data so the user data + * length is directly the fragment len. */ len = buf->len - (ptr - buf->data); @@ -390,37 +470,45 @@ static void setup_udp_recv(struct net_context *udp, void *user_data, } } -#if defined(CONFIG_NET_IPV4) -static bool send_ipv4_data(struct net_context *udp) +static bool send_udp_data(struct net_context *udp, + sa_family_t family, + char *proto, + struct data *data) { + bool status = false; struct net_buf *send_buf; struct sockaddr dst_addr; - bool status = false; + socklen_t addrlen; size_t len; int ret; - expecting_ipv4 = sys_rand32_get() % ipsum_len; + data->expecting_udp = sys_rand32_get() % ipsum_len; - send_buf = prepare_send_buf("IPv4", udp, expecting_ipv4); + send_buf = prepare_send_buf(proto, udp, data->expecting_udp); if (!send_buf) { goto out; } len = net_buf_frags_len(send_buf); - NET_ASSERT_INFO(expecting_ipv4 == len, + NET_ASSERT_INFO(data->expecting_udp == len, "Data to send %d bytes, real len %zu", - expecting_ipv4, len); + data->expecting_udp, len); - set_dst_addr(AF_INET, send_buf, &dst_addr); + set_dst_addr(family, send_buf, &dst_addr); + + if (family == AF_INET6) { + addrlen = sizeof(struct sockaddr_in6); + } else { + addrlen = sizeof(struct sockaddr_in); + } ret = net_context_sendto(send_buf, &dst_addr, - sizeof(struct sockaddr_in), - udp_sent, 0, + addrlen, udp_sent, 0, UINT_TO_POINTER(len), - "IPv4"); + proto); if (ret < 0) { - NET_ERR("Cannot send IPv4 data to peer (%d)", ret); + NET_ERR("Cannot send %s data to peer (%d)", proto, ret); net_nbuf_unref(send_buf); } else { status = true; @@ -430,145 +518,301 @@ out: return status; } -static void udp_ipv4_received(struct net_context *context, +static void udp_received(struct net_context *context, struct net_buf *buf, int status, void *user_data) { sa_family_t family = net_nbuf_family(buf); - struct k_sem *recv = user_data; + struct data *data = user_data; + struct k_sem *recv; ARG_UNUSED(context); ARG_UNUSED(status); if (family == AF_INET) { - if (expecting_ipv4 != net_nbuf_appdatalen(buf)) { - NET_ERR("Sent %d bytes, received %u bytes", - expecting_ipv4, net_nbuf_appdatalen(buf)); - } - - if (!compare_data(buf, expecting_ipv4)) { - NET_DBG("Data mismatch"); - } + recv = &conf.recv_ipv4; + } else { + recv = &conf.recv_ipv6; + } - net_nbuf_unref(buf); + if (data->expecting_udp != net_nbuf_appdatalen(buf)) { + NET_ERR("Sent %d bytes, received %u bytes", + data->expecting_udp, net_nbuf_appdatalen(buf)); + } - k_sem_give(recv); + if (!compare_udp_data(buf, data->expecting_udp)) { + NET_DBG("Data mismatch"); } + + net_nbuf_unref(buf); + + k_sem_give(recv); } -static void send_ipv4(struct net_context *udp) +static void send_udp(struct net_context *udp, + sa_family_t family, + char *proto, + struct k_sem *sem, + struct data *data) { - setup_udp_recv(udp, &recv_ipv4, udp_ipv4_received); + setup_udp_recv(udp, data, udp_received); - NET_INFO("Starting to send IPv4 data"); + NET_INFO("Starting to send %s data", proto); do { /* We first send a packet, then wait for a packet to arrive. * If the reply does not come in time, we send another packet. */ - send_ipv4_data(udp); + send_udp_data(udp, family, proto, data); - NET_DBG("Waiting IPv4 packet"); + NET_DBG("Waiting %s packet", proto); - if (!wait_reply("IPv4", &recv_ipv4)) { + if (!wait_reply(proto, sem)) { NET_DBG("Waited %d bytes but did not receive them.", - expecting_ipv4); + data->expecting_udp); } k_yield(); } while (1); } -#endif -#if defined(CONFIG_NET_IPV6) -static bool send_ipv6_data(struct net_context *udp) +#endif /* CONFIG_NET_UDP */ + +#if defined(CONFIG_NET_TCP) +static bool compare_tcp_data(struct net_buf *buf, int expecting_len, + int received_len) +{ + uint8_t *ptr = net_nbuf_appdata(buf), *start; + int pos = 0; + struct net_buf *frag; + int len; + + /* frag will point to first fragment with IP header in it. + */ + frag = buf->frags; + + /* Do not include the protocol headers for the first fragment. + * The remaining fragments contain only data so the user data + * length is directly the fragment len. + */ + len = frag->len - (ptr - frag->data); + + start = lorem_ipsum + received_len; + + while (frag) { + if (memcmp(ptr, start + pos, len)) { + NET_DBG("Invalid data received"); + return false; + } + + pos += len; + + frag = frag->frags; + if (!frag) { + break; + } + + ptr = frag->data; + len = frag->len; + } + + NET_DBG("Compared %d bytes, all ok", net_nbuf_appdatalen(buf)); + + return true; +} + +static void tcp_received(struct net_context *context, + struct net_buf *buf, + int status, + void *user_data) +{ + struct data *data = user_data; + char *proto; + + ARG_UNUSED(status); + + if (!buf || net_nbuf_appdatalen(buf) == 0) { + /* No need to unref the buf in this case, the IP stack + * will do it. + */ + return; + } + + if (net_nbuf_family(buf) == AF_INET6) { + proto = "IPv6"; + } else { + proto = "IPv4"; + } + + NET_DBG("Sent %d bytes, received %u bytes", + data->expecting_tcp, net_nbuf_appdatalen(buf)); + + if (!compare_tcp_data(buf, data->expecting_tcp, data->received_tcp)) { + NET_DBG("Data mismatch"); + } else { + data->received_tcp += net_nbuf_appdatalen(buf); + } + + if (data->expecting_tcp <= data->received_tcp) { + /* Send more data */ + send_tcp_data(context, proto, data); + } + + net_nbuf_unref(buf); +} + +static void setup_tcp_recv(struct net_context *tcp, + net_context_recv_cb_t cb, + void *user_data) +{ + int ret; + + ret = net_context_recv(tcp, cb, 0, user_data); + if (ret < 0) { + NET_ERR("Cannot receive TCP packets (%d)", ret); + } +} + +static void tcp_sent(struct net_context *context, + int status, + void *token, + void *user_data) +{ + uint32_t len = POINTER_TO_UINT(token); + + if (len) { + if (status) { + NET_DBG("%s: len %u status %d", (char *)user_data, + len, status); + } else { + NET_DBG("%s: len %u", (char *)user_data, len); + } + } +} + +static bool send_tcp_data(struct net_context *ctx, + char *proto, + struct data *data) { struct net_buf *send_buf; - struct sockaddr dst_addr; bool status = false; size_t len; int ret; - expecting_ipv6 = sys_rand32_get() % ipsum_len; + data->expecting_tcp = sys_rand32_get() % ipsum_len; + data->received_tcp = 0; - send_buf = prepare_send_buf("IPv6", udp, expecting_ipv6); + send_buf = prepare_send_buf(proto, ctx, data->expecting_tcp); if (!send_buf) { goto out; } len = net_buf_frags_len(send_buf); - NET_ASSERT_INFO(expecting_ipv6 == len, - "Data to send %d bytes, real len %zu", - expecting_ipv6, len); - - set_dst_addr(AF_INET6, send_buf, &dst_addr); + NET_ASSERT_INFO(data->expecting_tcp == len, + "%s data to send %d bytes, real len %zu", + proto, data->expecting_tcp, len); - ret = net_context_sendto(send_buf, &dst_addr, - sizeof(struct sockaddr_in6), - udp_sent, 0, - UINT_TO_POINTER(len), - "IPv6"); + ret = net_context_send(send_buf, tcp_sent, 0, + UINT_TO_POINTER(len), proto); if (ret < 0) { - NET_ERR("Cannot send IPv6 data to peer (%d)", ret); + NET_ERR("Cannot send %s data to peer (%d)", proto, ret); net_nbuf_unref(send_buf); } else { status = true; } -out: +out: return status; } -static void udp_ipv6_received(struct net_context *context, - struct net_buf *buf, - int status, - void *user_data) +static void tcp_connected(struct net_context *context, + int status, + void *user_data) { - sa_family_t family = net_nbuf_family(buf); - struct k_sem *recv = user_data; + /* Start to send data */ + sa_family_t family = POINTER_TO_UINT(user_data); - ARG_UNUSED(context); - ARG_UNUSED(status); + NET_DBG("%s connected.", family == AF_INET ? "IPv4" : "IPv6"); - if (family == AF_INET6) { - if (expecting_ipv6 != net_nbuf_appdatalen(buf)) { - NET_ERR("Sent %d bytes, received %d bytes", - expecting_ipv6, net_nbuf_appdatalen(buf)); - } + if (family == AF_INET) { +#if defined(CONFIG_NET_IPV4) + setup_tcp_recv(context, tcp_received, &conf.ipv4); - if (!compare_data(buf, expecting_ipv6)) { - NET_DBG("Data mismatch"); - } + send_tcp_data(context, "IPv4", &conf.ipv4); +#else + NET_DBG("IPv4 data skipped."); +#endif + } else if (family == AF_INET6) { +#if defined(CONFIG_NET_IPV6) + setup_tcp_recv(context, tcp_received, &conf.ipv6); + + send_tcp_data(context, "IPv6", &conf.ipv6); +#else + NET_DBG("IPv6 data skipped."); +#endif + } +} - net_nbuf_unref(buf); +#if defined(CONFIG_NET_IPV4) +static void tcp_connect4(struct net_context *tcp_send) +{ + int ret; - k_sem_give(recv); + ret = net_context_connect(tcp_send, + (struct sockaddr *)&peer_addr4, + sizeof(peer_addr4), + tcp_connected, + K_FOREVER, + UINT_TO_POINTER(AF_INET)); + if (ret < 0) { + NET_DBG("Cannot connect to IPv4 peer (%d)", ret); } } +#endif -static void send_ipv6(struct net_context *udp) +#if defined(CONFIG_NET_IPV6) +static void tcp_connect6(struct net_context *tcp_send) { - setup_udp_recv(udp, &recv_ipv6, udp_ipv6_received); + int ret; - NET_INFO("Starting to send IPv6 data"); + ret = net_context_connect(tcp_send, + (struct sockaddr *)&peer_addr6, + sizeof(peer_addr6), + tcp_connected, + K_FOREVER, + UINT_TO_POINTER(AF_INET6)); + if (ret < 0) { + NET_DBG("Cannot connect to IPv6 peer (%d)", ret); + } +} +#endif /* CONFIG_NET_IPV6 */ +#endif /* CONFIG_NET_TCP */ - do { - /* We first send a packet, then wait for a packet to arrive. - * If the reply does not come in time, we send another packet. - */ - send_ipv6_data(udp); +#if defined(CONFIG_NET_IPV4) +static void send_ipv4(struct net_context *udp, struct net_context *tcp) +{ +#if defined(CONFIG_NET_TCP) + tcp_connect4(tcp); +#endif - NET_DBG("Waiting IPv6 packet"); +#if defined(CONFIG_NET_UDP) + send_udp(udp, AF_INET, "IPv4", &conf.recv_ipv4, &conf.ipv4); +#endif +} +#endif - if (!wait_reply("IPv6", &recv_ipv6)) { - NET_DBG("Waited %d bytes but did not receive them.", - expecting_ipv6); - } +#if defined(CONFIG_NET_IPV6) +static void send_ipv6(struct net_context *udp, struct net_context *tcp) +{ +#if defined(CONFIG_NET_TCP) + tcp_connect6(tcp); +#endif - k_yield(); - } while (1); +#if defined(CONFIG_NET_UDP) + send_udp(udp, AF_INET6, "IPv6", &conf.recv_ipv6, &conf.ipv6); +#endif } #endif @@ -577,11 +821,15 @@ static void event_iface_up(struct net_mgmt_event_callback *cb, { struct net_context *udp_send4 = { 0 }; struct net_context *udp_send6 = { 0 }; + struct net_context *tcp_send4 = { 0 }; + struct net_context *tcp_send6 = { 0 }; struct net_context *mcast_send6 = { 0 }; ipsum_len = strlen(lorem_ipsum); - if (!get_context(&udp_send4, &udp_send6, &mcast_send6)) { + if (!get_context(&udp_send4, &udp_send6, + &tcp_send4, &tcp_send6, + &mcast_send6)) { NET_ERR("Cannot get network contexts"); return; } @@ -589,13 +837,13 @@ static void event_iface_up(struct net_mgmt_event_callback *cb, #if defined(CONFIG_NET_IPV4) k_thread_spawn(ipv4_stack, STACKSIZE, (k_thread_entry_t)send_ipv4, - udp_send4, NULL, NULL, K_PRIO_COOP(7), 0, 0); + udp_send4, tcp_send4, NULL, K_PRIO_COOP(7), 0, 0); #endif #if defined(CONFIG_NET_IPV6) k_thread_spawn(ipv6_stack, STACKSIZE, (k_thread_entry_t)send_ipv6, - udp_send6, NULL, NULL, K_PRIO_COOP(7), 0, 0); + udp_send6, tcp_send6, NULL, K_PRIO_COOP(7), 0, 0); #endif } diff --git a/samples/net/echo_server/prj_cc2520.conf b/samples/net/echo_server/prj_cc2520.conf index 16f93f0b9..aa4e9bed8 100644 --- a/samples/net/echo_server/prj_cc2520.conf +++ b/samples/net/echo_server/prj_cc2520.conf @@ -10,8 +10,6 @@ CONFIG_NET_NBUF_DATA_COUNT=40 CONFIG_NET_IPV4=n CONFIG_NET_IPV6=y CONFIG_NET_IPV6_RA_RDNSS=y -#CONFIG_NET_IPV6_NO_ND=y -#CONFIG_NET_IPV6_NO_DAD=y CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=2 CONFIG_NET_6LO=y diff --git a/samples/net/echo_server/prj_frdm_k64f_mcr20a.conf b/samples/net/echo_server/prj_frdm_k64f_mcr20a.conf new file mode 100644 index 000000000..e8f8d2ff0 --- /dev/null +++ b/samples/net/echo_server/prj_frdm_k64f_mcr20a.conf @@ -0,0 +1,46 @@ +CONFIG_NETWORKING=y + +CONFIG_NET_NBUF_RX_COUNT=20 +CONFIG_NET_NBUF_TX_COUNT=5 +CONFIG_NET_NBUF_DATA_COUNT=40 + +CONFIG_NET_IPV4=n +CONFIG_NET_IPV6=y +CONFIG_NET_IPV6_RA_RDNSS=y +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=2 + +CONFIG_NET_6LO=y +CONFIG_NET_DEBUG_6LO=n + +CONFIG_NET_LOG=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_INIT_STACKS=y +CONFIG_PRINTK=y + +CONFIG_NET_DEBUG_CORE=y +CONFIG_NET_DEBUG_IPV6_NBR_CACHE=y +CONFIG_NET_DEBUG_IPV6=y +CONFIG_NET_DEBUG_CONTEXT=y +CONFIG_NET_DEBUG_NET_BUF=n +CONFIG_NET_DEBUG_UTILS=n +CONFIG_NET_DEBUG_IF=n +CONFIG_NET_DEBUG_ICMPV6=y +CONFIG_NET_DEBUG_CONN=n +CONFIG_NET_STATISTICS=y +CONFIG_NET_STATISTICS_PERIODIC_OUTPUT=y + +CONFIG_NET_L2_IEEE802154=y +CONFIG_NET_DEBUG_L2_IEEE802154=y +CONFIG_NET_L2_IEEE802154_ORFD=y +CONFIG_NET_L2_IEEE802154_FRAGMENT=y +CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=n + +CONFIG_GPIO=y +CONFIG_SPI=y +CONFIG_SPI_0=y + +CONFIG_NXP_MCR20A=y +CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1 + +CONFIG_NET_SAMPLES_IP_ADDRESSES=y +CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::2" diff --git a/samples/net/echo_server/prj_slip.conf b/samples/net/echo_server/prj_slip.conf index 936990029..da8fa1e2d 100644 --- a/samples/net/echo_server/prj_slip.conf +++ b/samples/net/echo_server/prj_slip.conf @@ -1,3 +1,4 @@ + CONFIG_NETWORKING=y CONFIG_NET_IPV6=y CONFIG_NET_IPV4=y @@ -10,12 +11,12 @@ CONFIG_SYS_LOG_SHOW_COLOR=y CONFIG_INIT_STACKS=y CONFIG_PRINTK=y CONFIG_NET_STATISTICS=y -CONFIG_NET_NBUF_RX_COUNT=14 -CONFIG_NET_NBUF_TX_COUNT=14 -CONFIG_NET_NBUF_DATA_COUNT=30 +CONFIG_NET_NBUF_RX_COUNT=16 +CONFIG_NET_NBUF_TX_COUNT=16 +CONFIG_NET_NBUF_DATA_COUNT=40 CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2 -CONFIG_NET_MAX_CONTEXTS=10 +CONFIG_NET_MAX_CONTEXTS=16 CONFIG_NET_SHELL=y @@ -24,3 +25,6 @@ CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1" CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2" CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.0.2.1" CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.0.2.2" + +CONFIG_TELNET_CONSOLE=y +CONFIG_SYS_LOG_TELNET_CONSOLE_LEVEL=1 diff --git a/samples/net/echo_server/src/echo-server.c b/samples/net/echo_server/src/echo-server.c index 30b22bcdb..c92b54bc8 100644 --- a/samples/net/echo_server/src/echo-server.c +++ b/samples/net/echo_server/src/echo-server.c @@ -15,7 +15,6 @@ #include <zephyr.h> #include <sections.h> #include <errno.h> -#include <stdio.h> #include <net/nbuf.h> #include <net/net_if.h> @@ -376,7 +375,7 @@ static void udp_received(struct net_context *context, static char dbg[MAX_DBG_PRINT + 1]; int ret; - snprintf(dbg, MAX_DBG_PRINT, "UDP IPv%c", + snprintk(dbg, MAX_DBG_PRINT, "UDP IPv%c", family == AF_INET6 ? '6' : '4'); set_dst_addr(family, buf, &dst_addr); @@ -439,7 +438,7 @@ static void tcp_received(struct net_context *context, return; } - snprintf(dbg, MAX_DBG_PRINT, "TCP IPv%c", + snprintk(dbg, MAX_DBG_PRINT, "TCP IPv%c", family == AF_INET6 ? '6' : '4'); reply_buf = build_reply_buf(dbg, context, buf); diff --git a/samples/net/ieee802154/hw/prj.conf b/samples/net/ieee802154/hw/prj.conf index f0e91ab32..5af2d29b4 100644 --- a/samples/net/ieee802154/hw/prj.conf +++ b/samples/net/ieee802154/hw/prj.conf @@ -10,8 +10,6 @@ CONFIG_NET_NBUF_DATA_COUNT=10 CONFIG_NET_IPV4=n CONFIG_NET_IPV6=y CONFIG_NET_IPV6_RA_RDNSS=y -#CONFIG_NET_IPV6_NO_ND=y -#CONFIG_NET_IPV6_NO_DAD=y CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=2 CONFIG_NET_6LO=y diff --git a/samples/net/ieee802154/hw/prj_mcr20a.conf b/samples/net/ieee802154/hw/prj_mcr20a.conf new file mode 100644 index 000000000..271efe4d1 --- /dev/null +++ b/samples/net/ieee802154/hw/prj_mcr20a.conf @@ -0,0 +1,45 @@ +CONFIG_SPI=y +CONFIG_SYS_LOG_SPI_LEVEL=1 + +CONFIG_NETWORKING=y +CONFIG_TEST_RANDOM_GENERATOR=y + +CONFIG_NET_NBUF_RX_COUNT=6 +CONFIG_NET_NBUF_TX_COUNT=6 +CONFIG_NET_NBUF_DATA_COUNT=10 + +CONFIG_NET_IPV4=n +CONFIG_NET_IPV6=y +CONFIG_NET_IPV6_RA_RDNSS=y +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=2 + +CONFIG_NET_6LO=y +CONFIG_NET_DEBUG_6LO=y + +CONFIG_NET_LOG=y +CONFIG_SYS_LOG_NET_LEVEL=1 +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_INIT_STACKS=y +CONFIG_PRINTK=y + +CONFIG_NET_DEBUG_CORE=y +CONFIG_NET_DEBUG_IPV6_NBR_CACHE=y +CONFIG_NET_DEBUG_IPV6=y +CONFIG_NET_DEBUG_CONTEXT=y +CONFIG_NET_DEBUG_NET_BUF=y +CONFIG_NET_DEBUG_UTILS=y +CONFIG_NET_DEBUG_IF=y +CONFIG_NET_DEBUG_ICMPV6=y +CONFIG_NET_DEBUG_CONN=y +CONFIG_NET_STATISTICS=y + +CONFIG_NET_L2_IEEE802154=y +CONFIG_NET_DEBUG_L2_IEEE802154=y +CONFIG_NET_L2_IEEE802154_RFD=y +CONFIG_NET_L2_IEEE802154_FRAGMENT=y +#CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y + +CONFIG_NXP_MCR20A=y +CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1 + +CONFIG_NET_L2_IEEE802154_SHELL=y diff --git a/samples/net/ieee802154/hw/src/ieee802154_test.c b/samples/net/ieee802154/hw/src/ieee802154_test.c index f1eed4080..6bfe55fc9 100644 --- a/samples/net/ieee802154/hw/src/ieee802154_test.c +++ b/samples/net/ieee802154/hw/src/ieee802154_test.c @@ -15,6 +15,13 @@ #include <misc/printk.h> #define PRINT printk +#ifdef CONFIG_TI_CC2520_DRV_NAME +#define IEEE802154_DRV_NAME CONFIG_TI_CC2520_DRV_NAME +#endif +#ifdef CONFIG_NXP_MCR20A_DRV_NAME +#define IEEE802154_DRV_NAME CONFIG_NXP_MCR20A_DRV_NAME +#endif + #ifndef CONFIG_NET_L2_IEEE802154_SHELL static struct ieee802154_req_params scan_ctx; @@ -56,15 +63,15 @@ static struct net_if *init_device(void) struct net_if *iface; struct device *dev; - dev = device_get_binding(CONFIG_TI_CC2520_DRV_NAME); + dev = device_get_binding(IEEE802154_DRV_NAME); if (!dev) { - PRINT("Cannot get CC250 device\n"); + PRINT("Cannot get device binding\n"); return NULL; } iface = net_if_lookup_by_dev(dev); if (!iface) { - PRINT("Cannot get CC2520 network interface\n"); + PRINT("Cannot get 802.15.4 network interface\n"); return NULL; } diff --git a/samples/net/ieee802154/qemu/prj.conf b/samples/net/ieee802154/qemu/prj.conf index 074f80c03..6112e5164 100644 --- a/samples/net/ieee802154/qemu/prj.conf +++ b/samples/net/ieee802154/qemu/prj.conf @@ -8,8 +8,6 @@ CONFIG_NET_NBUF_DATA_COUNT=10 CONFIG_NET_IPV4=n CONFIG_NET_IPV6=y CONFIG_NET_IPV6_RA_RDNSS=y -#CONFIG_NET_IPV6_NO_ND=y -#CONFIG_NET_IPV6_NO_DAD=y CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=2 CONFIG_NET_6LO=y diff --git a/samples/net/leds_demo/src/leds-demo.c b/samples/net/leds_demo/src/leds-demo.c index f4904ca39..0fe8044d8 100644 --- a/samples/net/leds_demo/src/leds-demo.c +++ b/samples/net/leds_demo/src/leds-demo.c @@ -11,7 +11,6 @@ #endif #include <errno.h> -#include <stdio.h> #include <zephyr.h> #include <board.h> @@ -162,7 +161,7 @@ static int led_post(struct zoap_resource *resource, payload = zoap_packet_get_payload(request, &len); if (!payload) { - printf("packet without payload"); + printk("packet without payload"); return -EINVAL; } @@ -235,7 +234,7 @@ static int led_put(struct zoap_resource *resource, payload = zoap_packet_get_payload(request, &len); if (!payload) { - printf("packet without payload"); + printk("packet without payload"); return -EINVAL; } diff --git a/samples/net/mbedtls_dtlsclient/prj_qemu_x86.conf b/samples/net/mbedtls_dtlsclient/prj_qemu_x86.conf index fcdb263b9..cb693a032 100644 --- a/samples/net/mbedtls_dtlsclient/prj_qemu_x86.conf +++ b/samples/net/mbedtls_dtlsclient/prj_qemu_x86.conf @@ -3,7 +3,7 @@ CONFIG_NET_IPV6=n CONFIG_NET_IPV4=y CONFIG_NET_UDP=y CONFIG_NET_LOG=y -CONFIG_SLIP_TAP=y +CONFIG_NET_SLIP_TAP=y CONFIG_SYS_LOG=y CONFIG_SYS_LOG_SHOW_COLOR=y diff --git a/samples/net/mbedtls_dtlsserver/prj_qemu_x86.conf b/samples/net/mbedtls_dtlsserver/prj_qemu_x86.conf index 29bf043d5..fe66476d7 100644 --- a/samples/net/mbedtls_dtlsserver/prj_qemu_x86.conf +++ b/samples/net/mbedtls_dtlsserver/prj_qemu_x86.conf @@ -4,7 +4,7 @@ CONFIG_NET_IPV4=y CONFIG_NET_UDP=y CONFIG_NET_LOG=y CONFIG_NET_SLIP=y -CONFIG_SLIP_TAP=y +CONFIG_NET_SLIP_TAP=y CONFIG_SYS_LOG=y CONFIG_SYS_LOG_SHOW_COLOR=y diff --git a/samples/net/wpan_serial/src/main.c b/samples/net/wpan_serial/src/main.c index f40ec529a..a92e3b973 100644 --- a/samples/net/wpan_serial/src/main.c +++ b/samples/net/wpan_serial/src/main.c @@ -12,13 +12,14 @@ * with popular Contiki-based native border routers. */ -#include <stdio.h> #include <string.h> #include <device.h> #include <uart.h> #include <zephyr.h> #include <stdio.h> +#include <misc/printk.h> + #include <net/buf.h> #define SYS_LOG_DOMAIN "main" @@ -72,29 +73,29 @@ static void hexdump(const char *str, const uint8_t *packet, size_t length) int n = 0; if (!length) { - printf("%s zero-length signal packet\n", str); + printk("%s zero-length signal packet\n", str); return; } while (length--) { if (n % 16 == 0) { - printf("%s %08X ", str, n); + printk("%s %08X ", str, n); } - printf("%02X ", *packet++); + printk("%02X ", *packet++); n++; if (n % 8 == 0) { if (n % 16 == 0) { - printf("\n"); + printk("\n"); } else { - printf(" "); + printk(" "); } } } if (n % 16) { - printf("\n"); + printk("\n"); } } #else @@ -194,10 +195,19 @@ static void interrupt_handler(struct device *dev) while (uart_fifo_read(dev, &byte, sizeof(byte))) { if (slip_process_byte(byte)) { + /** + * slip_process_byte() returns 1 on + * SLIP_END, even after receiving full + * packet + */ + if (!pkt_curr) { + SYS_LOG_DBG("Skip SLIP_END"); + continue; + } + SYS_LOG_DBG("Full packet %p", pkt_curr); net_buf_put(&rx_queue, pkt_curr); - pkt_curr = NULL; } } @@ -304,7 +314,7 @@ static void process_data(struct net_buf *pkt) } /* Transmit data through radio */ - ret = radio_api->tx(ieee802154_dev, pkt); + ret = radio_api->tx(ieee802154_dev, pkt, buf); if (ret) { SYS_LOG_ERR("Error transmit data"); } @@ -560,20 +570,20 @@ void main(void) /* They are optional, we use them to test the interrupt endpoint */ ret = uart_line_ctrl_set(dev, LINE_CTRL_DCD, 1); if (ret) - printf("Failed to set DCD, ret code %d\n", ret); + printk("Failed to set DCD, ret code %d\n", ret); ret = uart_line_ctrl_set(dev, LINE_CTRL_DSR, 1); if (ret) - printf("Failed to set DSR, ret code %d\n", ret); + printk("Failed to set DSR, ret code %d\n", ret); /* Wait 1 sec for the host to do all settings */ sys_thread_busy_wait(1000000); #endif ret = uart_line_ctrl_get(dev, LINE_CTRL_BAUD_RATE, &baudrate); if (ret) - printf("Failed to get baudrate, ret code %d\n", ret); + printk("Failed to get baudrate, ret code %d\n", ret); else - printf("Baudrate detected: %d\n", baudrate); + printk("Baudrate detected: %d\n", baudrate); SYS_LOG_INF("USB serial initialized"); diff --git a/samples/net/wpanusb/src/wpanusb.c b/samples/net/wpanusb/src/wpanusb.c index 9d7eb97bf..528d93f2f 100644 --- a/samples/net/wpanusb/src/wpanusb.c +++ b/samples/net/wpanusb/src/wpanusb.c @@ -10,8 +10,8 @@ #include <sections.h> #include <toolchain.h> -#include <stdio.h> #include <string.h> +#include <misc/printk.h> #include <device.h> #include <uart.h> @@ -181,29 +181,29 @@ static void hexdump(const char *str, const uint8_t *packet, size_t length) int n = 0; if (!length) { - printf("%s zero-length signal packet\n", str); + printk("%s zero-length signal packet\n", str); return; } while (length--) { if (n % 16 == 0) { - printf("%s %08X ", str, n); + printk("%s %08X ", str, n); } - printf("%02X ", *packet++); + printk("%02X ", *packet++); n++; if (n % 8 == 0) { if (n % 16 == 0) { - printf("\n"); + printk("\n"); } else { - printf(" "); + printk(" "); } } } if (n % 16) { - printf("\n"); + printk("\n"); } } #else @@ -359,7 +359,7 @@ static int tx(struct net_buf *pkt) SYS_LOG_DBG("len %d seq %u", buf->len, seq); do { - ret = radio_api->tx(ieee802154_dev, pkt); + ret = radio_api->tx(ieee802154_dev, pkt, buf); } while (ret && retries--); if (ret) { @@ -568,7 +568,7 @@ int net_recv_data(struct net_if *iface, struct net_buf *buf) static int shell_cmd_help(int argc, char *argv[]) { /* Keep the commands in alphabetical order */ - printf("wpanusb help\n"); + printk("wpanusb help\n"); return 0; } diff --git a/samples/net/zoap_client/README.rst b/samples/net/zoap_client/README.rst new file mode 100644 index 000000000..02f2fee50 --- /dev/null +++ b/samples/net/zoap_client/README.rst @@ -0,0 +1,46 @@ +CoAP client +########### + +Overview +******** + +A simple CoAP server showing how to retrieve information from a resource. + +This demo assumes that the platform of choice has networking support, +some adjustments to the configuration may be needed. + +This sample will make a GET request with path 'test' to the IPv6 +multicast address reserved for CoAP nodes, so the URI can be +represented as: + +.. code-block:: none + + coap://[ff02::fd]:5683/test + +Building and Running +******************** + +This project will print all the octets of the response received, more context can +be obtained by using a tool like tcpdump or wireshark. + +See the `net-tools`_ project for more details. + +It can be built and executed on QEMU as follows: + +.. code-block:: console + + make run + +Sample output +------------- + +.. code-block:: console + + reply: 60 00 00 00 00 24 11 40 fe 80 00 00 00 00 00 00 5c 25 e2 ff fe + 15 01 01 fe 80 00 00 00 00 00 00 5c 25 e2 ff fe 15 01 01 16 33 16 33 + 00 24 3d 86 60 40 00 01 ff 54 79 70 65 3a 20 30 0a 43 6f 64 65 3a 20 + 31 0a 4d 49 44 3a 20 31 0a (76 bytes) + +.. note: The values shown above might differ. + +.. _`net-tools`: https://gerrit.zephyrproject.org/r/gitweb?p=net-tools.git;a=tree diff --git a/samples/net/zoap_client/README.txt b/samples/net/zoap_client/README.txt deleted file mode 100644 index 5b45c13c2..000000000 --- a/samples/net/zoap_client/README.txt +++ /dev/null @@ -1,54 +0,0 @@ -Title: CoAP client - -Description: - -A simple CoAP server showing how to retrieve information from a resource. - -This demo assumes that the platform of choice has networking support, -some adjustments to the configuration may be needed. - -This sample will make a GET request with path 'test' to the IPv6 -multicast address reserved for CoAP nodes, so the URI can be -represented as: - -coap://[ff02::fd]:5683/test - --------------------------------------------------------------------------------- - -Building and Running Project: - -This project will print all the octets of the response received, more context can -be obtained by using a tool like tcpdump or wireshark. - -See the net-tools[1] project for more details. - -It can be built and executed on QEMU as follows: - - make run - -[1] net-tools: - https://gerrit.zephyrproject.org/r/gitweb?p=net-tools.git;a=tree - --------------------------------------------------------------------------------- - -Troubleshooting: - -Problems caused by out-dated project information can be addressed by -issuing one of the following commands then rebuilding the project: - - make clean # discard results of previous builds - # but keep existing configuration info -or - make pristine # discard results of previous builds - # and restore pre-defined configuration info - -------------------------------------------------------------------------------- - -Sample output: - -reply: 60 00 00 00 00 24 11 40 fe 80 00 00 00 00 00 00 5c 25 e2 ff fe -15 01 01 fe 80 00 00 00 00 00 00 5c 25 e2 ff fe 15 01 01 16 33 16 33 -00 24 3d 86 60 40 00 01 ff 54 79 70 65 3a 20 30 0a 43 6f 64 65 3a 20 -31 0a 4d 49 44 3a 20 31 0a (76 bytes) - -<the values may be different> diff --git a/samples/net/zoap_client/src/zoap-client.c b/samples/net/zoap_client/src/zoap-client.c index d47b2b635..984afa451 100644 --- a/samples/net/zoap_client/src/zoap-client.c +++ b/samples/net/zoap_client/src/zoap-client.c @@ -5,7 +5,7 @@ */ #include <errno.h> -#include <stdio.h> +#include <misc/printk.h> #include <zephyr.h> @@ -50,10 +50,10 @@ static void msg_dump(const char *s, uint8_t *data, unsigned len) { unsigned i; - printf("%s: ", s); + printk("%s: ", s); for (i = 0; i < len; i++) - printf("%02x ", data[i]); - printf("(%u bytes)\n", len); + printk("%02x ", data[i]); + printk("(%u bytes)\n", len); } static int resource_reply_cb(const struct zoap_packet *response, @@ -87,7 +87,7 @@ static void udp_receive(struct net_context *context, r = zoap_packet_parse(&response, buf); if (r < 0) { - printf("Invalid data received (%d)\n", r); + printk("Invalid data received (%d)\n", r); return; } @@ -104,7 +104,7 @@ static void udp_receive(struct net_context *context, (const struct sockaddr *) &from, replies, NUM_REPLIES); if (!reply) { - printf("No handler for response (%d)\n", r); + printk("No handler for response (%d)\n", r); return; } } @@ -154,20 +154,20 @@ static void event_iface_up(struct net_mgmt_event_callback *cb, r = net_context_get(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &context); if (r) { - printf("Could not get an UDP context\n"); + printk("Could not get an UDP context\n"); return; } r = net_context_bind(context, (struct sockaddr *) &any_addr, sizeof(any_addr)); if (r) { - printf("Could not bind the context\n"); + printk("Could not bind the context\n"); return; } r = net_context_recv(context, udp_receive, 0, NULL); if (r) { - printf("Could not receive in the context\n"); + printk("Could not receive in the context\n"); return; } @@ -175,13 +175,13 @@ static void event_iface_up(struct net_mgmt_event_callback *cb, buf = net_nbuf_get_tx(context); if (!buf) { - printf("Unable to get TX buffer, not enough memory.\n"); + printk("Unable to get TX buffer, not enough memory.\n"); return; } frag = net_nbuf_get_data(context); if (!frag) { - printf("Unable to get DATA buffer, not enough memory.\n"); + printk("Unable to get DATA buffer, not enough memory.\n"); return; } @@ -203,7 +203,7 @@ static void event_iface_up(struct net_mgmt_event_callback *cb, r = zoap_add_option(&request, ZOAP_OPTION_OBSERVE, &observe, sizeof(observe)); if (r < 0) { - printf("Unable add option to request.\n"); + printk("Unable add option to request.\n"); return; } @@ -211,27 +211,27 @@ static void event_iface_up(struct net_mgmt_event_callback *cb, r = zoap_add_option(&request, ZOAP_OPTION_URI_PATH, *p, strlen(*p)); if (r < 0) { - printf("Unable add option to request.\n"); + printk("Unable add option to request.\n"); return; } } pending = zoap_pending_next_unused(pendings, NUM_PENDINGS); if (!pending) { - printf("Unable to find a free pending to track " + printk("Unable to find a free pending to track " "retransmissions.\n"); return; } r = zoap_pending_init(pending, &request); if (r < 0) { - printf("Unable to initialize a pending retransmission.\n"); + printk("Unable to initialize a pending retransmission.\n"); return; } reply = zoap_reply_next_unused(replies, NUM_REPLIES); if (!reply) { - printf("No resources for waiting for replies.\n"); + printk("No resources for waiting for replies.\n"); return; } @@ -242,7 +242,7 @@ static void event_iface_up(struct net_mgmt_event_callback *cb, sizeof(mcast_addr), NULL, 0, NULL, NULL); if (r < 0) { - printf("Error sending the packet (%d).\n", r); + printk("Error sending the packet (%d).\n", r); return; } diff --git a/samples/net/zoap_server/README.rst b/samples/net/zoap_server/README.rst new file mode 100644 index 000000000..a3c320e4d --- /dev/null +++ b/samples/net/zoap_server/README.rst @@ -0,0 +1,40 @@ +CoAP Server +########### + +Overview +******** + +A simple CoAP server showing how to expose a simple resource. + +This demo assumes that the platform of choice has networking support, +some adjustments to the configuration may be needed. + +The sample will listen for requests in the CoAP UDP port (5683) in the +site-local IPv6 multicast address reserved for CoAP nodes. + +The exported resource, with path '/test', will just respond any GET to +that path with the the type, code and message identification retrieved +from the request. The response will have this format: + +.. code-block:: none + + Type: <type> + Code: <code> + MID: <message id> + +Building And Running +******************** + +This project has no output in case of success, the correct +functionality can be verified by using some external tool like tcpdump +or wireshark. + +See the `net-tools`_ project for more details + +It can be built and executed on QEMU as follows: + +.. code-block:: console + + make run + +.. _`net-tools`: https://gerrit.zephyrproject.org/r/gitweb?p=net-tools.git;a=tree diff --git a/samples/net/zoap_server/README.txt b/samples/net/zoap_server/README.txt deleted file mode 100644 index be5f83632..000000000 --- a/samples/net/zoap_server/README.txt +++ /dev/null @@ -1,51 +0,0 @@ -Title: CoAP Server - -Description: - -A simple CoAP server showing how to expose a simple resource. - -This demo assumes that the platform of choice has networking support, -some adjustments to the configuration may be needed. - -The sample will listen for requests in the CoAP UDP port (5683) in the -site-local IPv6 multicast address reserved for CoAP nodes. - -The exported resource, with path '/test', will just respond any GET to -that path with the the type, code and message identification retrieved -from the request. The response will have this format: - -Type: <type> -Code: <code> -MID: <message id> - --------------------------------------------------------------------------------- - -Building and Running Project: - -This project has no output in case of success, the correct -functionality can be verified by using some external tool like tcpdump -or wireshark. - -See the net-tools[1] project for more details - -It can be built and executed on QEMU as follows: - - make run - -[1] net-tools: - https://gerrit.zephyrproject.org/r/gitweb?p=net-tools.git;a=tree - --------------------------------------------------------------------------------- - -Troubleshooting: - -Problems caused by out-dated project information can be addressed by -issuing one of the following commands then rebuilding the project: - - make clean # discard results of previous builds - # but keep existing configuration info -or - make pristine # discard results of previous builds - # and restore pre-defined configuration info - -------------------------------------------------------------------------------- diff --git a/samples/net/zoap_server/src/zoap-server.c b/samples/net/zoap_server/src/zoap-server.c index e2db7fc6f..ab12d8282 100644 --- a/samples/net/zoap_server/src/zoap-server.c +++ b/samples/net/zoap_server/src/zoap-server.c @@ -11,7 +11,7 @@ #endif #include <errno.h> -#include <stdio.h> +#include <misc/printk.h> #include <zephyr.h> @@ -37,6 +37,9 @@ #define ALL_NODES_LOCAL_COAP_MCAST \ { { { 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xfd } } } +#define MY_IP6ADDR \ + { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } } + static struct net_context *context; static const uint8_t plain_text_format; @@ -369,8 +372,8 @@ static int piggyback_get(struct zoap_resource *resource, } /* The response that coap-client expects */ - r = snprintf((char *) payload, len, "Type: %u\nCode: %u\nMID: %u\n", - type, code, id); + r = snprintk((char *) payload, len, + "Type: %u\nCode: %u\nMID: %u\n", type, code, id); if (r < 0 || r > len) { return -EINVAL; } @@ -464,8 +467,8 @@ static int query_get(struct zoap_resource *resource, } /* The response that coap-client expects */ - r = snprintf((char *) payload, len, "Type: %u\nCode: %u\nMID: %u\n", - type, code, id); + r = snprintk((char *) payload, len, + "Type: %u\nCode: %u\nMID: %u\n", type, code, id); if (r < 0 || r > len) { return -EINVAL; } @@ -582,8 +585,8 @@ done: } /* The response that coap-client expects */ - r = snprintf((char *) payload, len, "Type: %u\nCode: %u\nMID: %u\n", - type, code, id); + r = snprintk((char *) payload, len, + "Type: %u\nCode: %u\nMID: %u\n", type, code, id); if (r < 0 || r > len) { return -EINVAL; } @@ -855,11 +858,13 @@ static void udp_receive(struct net_context *context, static bool join_coap_multicast_group(void) { + static struct in6_addr my_addr = MY_IP6ADDR; static struct sockaddr_in6 mcast_addr = { .sin6_family = AF_INET6, .sin6_addr = ALL_NODES_LOCAL_COAP_MCAST, .sin6_port = htons(MY_COAP_PORT) }; struct net_if_mcast_addr *mcast; + struct net_if_addr *ifaddr; struct net_if *iface; iface = net_if_get_default(); @@ -868,6 +873,18 @@ static bool join_coap_multicast_group(void) return false; } +#if defined(CONFIG_NET_SAMPLES_IP_ADDRESSES) + if (net_addr_pton(AF_INET6, + CONFIG_NET_SAMPLES_MY_IPV6_ADDR, + (struct sockaddr *)&my_addr) < 0) { + NET_ERR("Invalid IPv6 address %s", + CONFIG_NET_SAMPLES_MY_IPV6_ADDR); + } +#endif + + ifaddr = net_if_ipv6_addr_add(iface, &my_addr, NET_ADDR_MANUAL, 0); + ifaddr->addr_state = NET_ADDR_PREFERRED; + mcast = net_if_ipv6_maddr_add(iface, &mcast_addr.sin6_addr); if (!mcast) { NET_ERR("Could not add multicast address to interface\n"); @@ -881,7 +898,7 @@ void main(void) { static struct sockaddr_in6 any_addr = { .sin6_family = AF_INET6, - .sin6_addr = ALL_NODES_LOCAL_COAP_MCAST, + .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(MY_COAP_PORT) }; int r; |