diff --git a/subsys/net/lib/app/client.c b/subsys/net/lib/app/client.c index 995e28e8e7d1d..8f62034f514db 100644 --- a/subsys/net/lib/app/client.c +++ b/subsys/net/lib/app/client.c @@ -104,6 +104,95 @@ static int resolve_name(struct net_app_ctx *ctx, } #endif /* CONFIG_DNS_RESOLVER */ +static int try_resolve(struct net_app_ctx *ctx, + const char *peer_addr_str, + enum dns_query_type type, + s32_t timeout) +{ +#if !defined(CONFIG_DNS_RESOLVER) + NET_ERR("Invalid IP address %s", peer_addr_str); + return -EINVAL; +#else + int ret; + + ret = resolve_name(ctx, peer_addr_str, type, timeout); + if (ret < 0) { + NET_ERR("Cannot resolve %s (%d)", peer_addr_str, ret); + } + + return ret; +#endif +} + +static int set_remote_addr(struct net_app_ctx *ctx, + struct sockaddr *remote_addr, + const char *peer_addr_str, + bool peer_addr_ok, + s32_t timeout) +{ + int ret; + + if (peer_addr_ok && remote_addr->sa_family == AF_INET6) { +#if defined(CONFIG_NET_IPV6) + memcpy(&ctx->ipv6.remote, remote_addr, + sizeof(struct sockaddr)); + ctx->default_ctx = &ctx->ipv6; + return 0; +#else + return -EAFNOSUPPORT; +#endif + } + + if (peer_addr_ok && remote_addr->sa_family == AF_INET) { +#if defined(CONFIG_NET_IPV4) + memcpy(&ctx->ipv4.remote, remote_addr, + sizeof(struct sockaddr)); + ctx->default_ctx = &ctx->ipv4; + return 0; +#else + return -EAFNOSUPPORT; +#endif + } + +#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4) + /* Could be hostname, try DNS if configured. */ + ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_AAAA, timeout); + if (ret < 0) { + return ret; + } + + ctx->default_ctx = &ctx->ipv6; + return 0; +#endif /* IPV6 && !IPV4 */ + +#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) + ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_A, timeout); + if (ret < 0) { + return ret; + } + + ctx->default_ctx = &ctx->ipv4; + return 0; +#endif /* IPV6 && !IPV4 */ + +#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6) + ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_A, timeout); + if (ret < 0) { + ret = try_resolve(ctx, peer_addr_str, DNS_QUERY_TYPE_AAAA, + timeout); + if (ret < 0) { + return ret; + } + + ctx->default_ctx = &ctx->ipv6; + return 0; + } + + ctx->default_ctx = &ctx->ipv4; + return 0; +#endif /* IPV4 && IPV6 */ +} + static int get_port_number(const char *peer_addr_str, char *buf, size_t buf_len) @@ -168,132 +257,26 @@ static int get_port_number(const char *peer_addr_str, return 0; } -static int set_remote_addr(struct net_app_ctx *ctx, - const char *peer_addr_str, - u16_t peer_port, - s32_t timeout) +static void close_net_ctx(struct net_app_ctx *ctx) { - char addr_str[INET6_ADDRSTRLEN + 1]; - char *addr; - int ret; - - /* If the peer string contains port number, use that and ignore - * the port number parameter. - */ - ret = get_port_number(peer_addr_str, addr_str, sizeof(addr_str)); - if (ret > 0) { - addr = addr_str; - peer_port = ret; - } else { - addr = (char *)peer_addr_str; +#if defined(CONFIG_NET_IPV6) + if (ctx->ipv6.ctx) { + net_context_put(ctx->ipv6.ctx); + ctx->ipv6.ctx = NULL; } - -#if defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4) - ret = net_addr_pton(AF_INET6, addr, - &net_sin6(&ctx->ipv6.remote)->sin6_addr); - if (ret < 0) { - /* Could be hostname, try DNS if configured. */ -#if !defined(CONFIG_DNS_RESOLVER) - NET_ERR("Invalid IPv6 address %s", addr); - return -EINVAL; -#else - ret = resolve_name(ctx, addr, DNS_QUERY_TYPE_AAAA, timeout); - if (ret < 0) { - NET_ERR("Cannot resolve %s (%d)", addr, ret); - return ret; - } #endif +#if defined(CONFIG_NET_IPV4) + if (ctx->ipv4.ctx) { + net_context_put(ctx->ipv4.ctx); + ctx->ipv4.ctx = NULL; } - - net_sin6(&ctx->ipv6.remote)->sin6_port = htons(peer_port); - net_sin6(&ctx->ipv6.remote)->sin6_family = AF_INET6; - ctx->ipv6.remote.sa_family = AF_INET6; - ctx->default_ctx = &ctx->ipv6; -#endif /* IPV6 && !IPV4 */ - -#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_IPV6) - ret = net_addr_pton(AF_INET, addr, - &net_sin(&ctx->ipv4.remote)->sin_addr); - if (ret < 0) { - /* Could be hostname, try DNS if configured. */ -#if !defined(CONFIG_DNS_RESOLVER) - NET_ERR("Invalid IPv4 address %s", addr); - return -EINVAL; -#else - ret = resolve_name(ctx, addr, DNS_QUERY_TYPE_A, timeout); - if (ret < 0) { - NET_ERR("Cannot resolve %s (%d)", addr, ret); - return ret; - } #endif +#if defined(CONFIG_NET_APP_SERVER) + if (ctx->server.net_ctx) { + net_context_put(ctx->server.net_ctx); + ctx->server.net_ctx = NULL; } - - net_sin(&ctx->ipv4.remote)->sin_port = htons(peer_port); - net_sin(&ctx->ipv4.remote)->sin_family = AF_INET; - ctx->ipv4.remote.sa_family = AF_INET; - ctx->default_ctx = &ctx->ipv4; -#endif /* IPV6 && !IPV4 */ - -#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6) - ret = net_addr_pton(AF_INET, addr, - &net_sin(&ctx->ipv4.remote)->sin_addr); - if (ret < 0) { - ret = net_addr_pton(AF_INET6, addr, - &net_sin6(&ctx->ipv6.remote)->sin6_addr); - if (ret < 0) { - /* Could be hostname, try DNS if configured. */ -#if !defined(CONFIG_DNS_RESOLVER) - NET_ERR("Invalid IPv4 or IPv6 address %s", addr); - return -EINVAL; -#else - ret = resolve_name(ctx, addr, - DNS_QUERY_TYPE_A, timeout); - if (ret < 0) { - ret = resolve_name(ctx, addr, - DNS_QUERY_TYPE_AAAA, - timeout); - if (ret < 0) { - NET_ERR("Cannot resolve %s (%d)", - addr, ret); - return ret; - } - - goto ipv6; - } - - goto ipv4; -#endif /* !CONFIG_DNS_RESOLVER */ - } else { -#if defined(CONFIG_DNS_RESOLVER) - ipv6: #endif - net_sin6(&ctx->ipv6.remote)->sin6_port = - htons(peer_port); - net_sin6(&ctx->ipv6.remote)->sin6_family = AF_INET6; - ctx->ipv6.remote.sa_family = AF_INET6; - ctx->default_ctx = &ctx->ipv6; - } - } else { -#if defined(CONFIG_DNS_RESOLVER) - ipv4: -#endif - net_sin(&ctx->ipv4.remote)->sin_port = htons(peer_port); - net_sin(&ctx->ipv4.remote)->sin_family = AF_INET; - ctx->ipv4.remote.sa_family = AF_INET; - ctx->default_ctx = &ctx->ipv4; - } -#endif /* IPV4 && IPV6 */ - - /* If we have not yet figured out what is the protocol family, - * then we cannot continue. - */ - if (!ctx->default_ctx || - ctx->default_ctx->remote.sa_family == AF_UNSPEC) { - NET_ERR("Unknown protocol family."); - return -EPFNOSUPPORT; - } - - return 0; } int net_app_init_client(struct net_app_ctx *ctx, @@ -306,8 +289,11 @@ int net_app_init_client(struct net_app_ctx *ctx, s32_t timeout, void *user_data) { + const char *base_peer_addr = peer_addr_str; + char base_addr_str[INET6_ADDRSTRLEN + 1]; + struct sockaddr remote_addr; struct sockaddr addr; - int ret; + int ret, addr_ok = false; if (!ctx) { return -EINVAL; @@ -318,11 +304,54 @@ int net_app_init_client(struct net_app_ctx *ctx, } memset(&addr, 0, sizeof(addr)); + memset(&remote_addr, 0, sizeof(remote_addr)); + + if (peer_addr) { + memcpy(&remote_addr, peer_addr, sizeof(remote_addr)); + } else if (peer_addr_str) { + /* If the peer string contains port number, use that and + * ignore the port number parameter. + */ + ret = get_port_number(peer_addr_str, base_addr_str, + sizeof(base_addr_str)); + if (ret > 0) { + base_peer_addr = base_addr_str; + peer_port = ret; + } else { + strncpy(base_addr_str, peer_addr_str, + sizeof(base_addr_str) - 1); + } + + addr_ok = net_ipaddr_parse(base_peer_addr, + strlen(base_peer_addr), + &remote_addr); + +#if defined(CONFIG_NET_IPV6) + if (remote_addr.sa_family == AF_INET6) { + net_sin6(&remote_addr)->sin6_port = htons(peer_port); + } +#endif +#if defined(CONFIG_NET_IPV4) + if (remote_addr.sa_family == AF_INET) { + net_sin(&remote_addr)->sin_port = htons(peer_port); + } +#endif + + /* The remote_addr will be used by set_remote_addr() to + * set the actual peer address. + */ + } if (client_addr) { memcpy(&addr, client_addr, sizeof(addr)); + + if (addr.sa_family != remote_addr.sa_family) { + NET_DBG("Address family mismatch %d vs %d", + addr.sa_family, remote_addr.sa_family); + return -EINVAL; + } } else { - addr.sa_family = AF_UNSPEC; + addr.sa_family = remote_addr.sa_family; } ctx->app_type = NET_APP_CLIENT; @@ -334,6 +363,7 @@ int net_app_init_client(struct net_app_ctx *ctx, ret = _net_app_config_local_ctx(ctx, sock_type, proto, &addr); if (ret < 0) { + close_net_ctx(ctx); goto fail; } @@ -362,14 +392,26 @@ int net_app_init_client(struct net_app_ctx *ctx, if (!peer_addr_str) { NET_ERR("Cannot know where to connect."); ret = -EINVAL; + close_net_ctx(ctx); goto fail; } - ret = set_remote_addr(ctx, peer_addr_str, peer_port, timeout); + ret = set_remote_addr(ctx, &remote_addr, base_addr_str, + addr_ok, timeout); if (ret < 0) { + close_net_ctx(ctx); goto fail; } + /* If we have not yet figured out what is the protocol family, + * then we cannot continue. + */ + if (!ctx->default_ctx || + ctx->default_ctx->remote.sa_family == AF_UNSPEC) { + NET_ERR("Unknown protocol family."); + return -EPFNOSUPPORT; + } + #if defined(CONFIG_NET_IPV4) if (ctx->ipv4.remote.sa_family == AF_INET) { ctx->ipv4.local.sa_family = AF_INET; diff --git a/subsys/net/lib/app/net_app.c b/subsys/net/lib/app/net_app.c index b9d6a83436565..c3a6b811044a7 100644 --- a/subsys/net/lib/app/net_app.c +++ b/subsys/net/lib/app/net_app.c @@ -852,9 +852,6 @@ int net_app_close(struct net_app_ctx *ctx) } net_ctx = _net_app_select_net_ctx(ctx, NULL); - if (!net_ctx) { - return -EAFNOSUPPORT; - } if (ctx->cb.close) { ctx->cb.close(ctx, 0, ctx->user_data); @@ -866,7 +863,9 @@ int net_app_close(struct net_app_ctx *ctx) } #endif - net_context_put(net_ctx); + if (net_ctx) { + net_context_put(net_ctx); + } return 0; } diff --git a/tests/net/app/Makefile b/tests/net/app/Makefile new file mode 100644 index 0000000000000..4b05dca8edb6d --- /dev/null +++ b/tests/net/app/Makefile @@ -0,0 +1,4 @@ +BOARD ?= qemu_x86 +CONF_FILE = prj.conf + +include $(ZEPHYR_BASE)/Makefile.test diff --git a/tests/net/app/prj-no-ipv4.conf b/tests/net/app/prj-no-ipv4.conf new file mode 100644 index 0000000000000..bd8b99ea61388 --- /dev/null +++ b/tests/net/app/prj-no-ipv4.conf @@ -0,0 +1,32 @@ +CONFIG_NETWORKING=y +CONFIG_NET_TEST=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV4=n +CONFIG_NET_UDP=y +CONFIG_NET_TCP=y +CONFIG_NET_DHCPV4=n +CONFIG_NET_MAX_CONTEXTS=10 +CONFIG_NET_L2_DUMMY=y +CONFIG_NET_LOG=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_RANDOM_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_IPV6_DAD=n +CONFIG_NET_IPV6_MLD=n +CONFIG_NET_IPV6_ND=n +CONFIG_NET_PKT_TX_COUNT=10 +CONFIG_NET_PKT_RX_COUNT=10 +CONFIG_NET_BUF_RX_COUNT=10 +CONFIG_NET_BUF_TX_COUNT=10 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=6 +CONFIG_NET_IPV6_MAX_NEIGHBORS=8 +CONFIG_NET_APP=y +CONFIG_NET_APP_AUTO_INIT=n +CONFIG_NET_APP_SERVER=y +CONFIG_NET_APP_CLIENT=y +CONFIG_NET_APP_SETTINGS=y +CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1" +CONFIG_ZTEST=y +#CONFIG_NET_DEBUG_APP=y +#CONFIG_SYS_LOG_NET_LEVEL=4 +#CONFIG_NET_SHELL=y diff --git a/tests/net/app/prj-no-ipv6.conf b/tests/net/app/prj-no-ipv6.conf new file mode 100644 index 0000000000000..a8db32f3d0c0b --- /dev/null +++ b/tests/net/app/prj-no-ipv6.conf @@ -0,0 +1,28 @@ +CONFIG_NETWORKING=y +CONFIG_NET_TEST=y +CONFIG_NET_IPV6=n +CONFIG_NET_IPV4=y +CONFIG_NET_UDP=y +CONFIG_NET_TCP=y +CONFIG_NET_DHCPV4=n +CONFIG_NET_MAX_CONTEXTS=10 +CONFIG_NET_L2_DUMMY=y +CONFIG_NET_LOG=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_RANDOM_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_PKT_TX_COUNT=10 +CONFIG_NET_PKT_RX_COUNT=10 +CONFIG_NET_BUF_RX_COUNT=10 +CONFIG_NET_BUF_TX_COUNT=10 +CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 +CONFIG_NET_APP=y +CONFIG_NET_APP_AUTO_INIT=n +CONFIG_NET_APP_SERVER=y +CONFIG_NET_APP_CLIENT=y +CONFIG_NET_APP_SETTINGS=y +CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1" +CONFIG_ZTEST=y +#CONFIG_NET_DEBUG_APP=y +#CONFIG_SYS_LOG_NET_LEVEL=4 +#CONFIG_NET_SHELL=y diff --git a/tests/net/app/prj-with-dns.conf b/tests/net/app/prj-with-dns.conf new file mode 100644 index 0000000000000..6e4eaaf8bb5bf --- /dev/null +++ b/tests/net/app/prj-with-dns.conf @@ -0,0 +1,46 @@ +CONFIG_NETWORKING=y +CONFIG_NET_TEST=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV4=y +CONFIG_NET_UDP=y +CONFIG_NET_TCP=y +CONFIG_NET_DHCPV4=n +CONFIG_NET_MAX_CONTEXTS=10 +CONFIG_NET_L2_DUMMY=y +CONFIG_NET_LOG=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_RANDOM_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_IPV6_DAD=n +CONFIG_NET_IPV6_MLD=n +CONFIG_NET_IPV6_ND=n +CONFIG_NET_PKT_TX_COUNT=10 +CONFIG_NET_PKT_RX_COUNT=10 +CONFIG_NET_BUF_RX_COUNT=10 +CONFIG_NET_BUF_TX_COUNT=10 +CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=6 +CONFIG_NET_IPV6_MAX_NEIGHBORS=8 +CONFIG_NET_APP=y +CONFIG_NET_APP_AUTO_INIT=n +CONFIG_NET_APP_SERVER=y +CONFIG_NET_APP_CLIENT=y +CONFIG_NET_APP_SETTINGS=y +CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1" +CONFIG_ZTEST=y + +CONFIG_DNS_RESOLVER=y +CONFIG_DNS_RESOLVER_MAX_SERVERS=4 +CONFIG_DNS_NUM_OF_CONCUR_QUERIES=1 +CONFIG_DNS_SERVER_IP_ADDRESSES=y +CONFIG_DNS_SERVER1="192.0.2.2" +CONFIG_DNS_SERVER2="2001:db8::2" +CONFIG_DNS_SERVER3="192.0.2.2:5353" +CONFIG_DNS_SERVER4="[2001:db8::2]:5353" + +#CONFIG_NET_DEBUG_DNS_RESOLVE=y +#CONFIG_NET_DEBUG_APP=y +#CONFIG_SYS_LOG_NET_LEVEL=4 +#CONFIG_NET_SHELL=y diff --git a/tests/net/app/prj.conf b/tests/net/app/prj.conf new file mode 100644 index 0000000000000..f0f6d9cd6b40e --- /dev/null +++ b/tests/net/app/prj.conf @@ -0,0 +1,35 @@ +CONFIG_NETWORKING=y +CONFIG_NET_TEST=y +CONFIG_NET_IPV6=y +CONFIG_NET_IPV4=y +CONFIG_NET_UDP=y +CONFIG_NET_TCP=y +CONFIG_NET_DHCPV4=n +CONFIG_NET_MAX_CONTEXTS=10 +CONFIG_NET_L2_DUMMY=y +CONFIG_NET_LOG=y +CONFIG_SYS_LOG_SHOW_COLOR=y +CONFIG_RANDOM_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_NET_IPV6_DAD=n +CONFIG_NET_IPV6_MLD=n +CONFIG_NET_IPV6_ND=n +CONFIG_NET_PKT_TX_COUNT=10 +CONFIG_NET_PKT_RX_COUNT=10 +CONFIG_NET_BUF_RX_COUNT=10 +CONFIG_NET_BUF_TX_COUNT=10 +CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3 +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=6 +CONFIG_NET_IPV6_MAX_NEIGHBORS=8 +CONFIG_NET_APP=y +CONFIG_NET_APP_AUTO_INIT=n +CONFIG_NET_APP_SERVER=y +CONFIG_NET_APP_CLIENT=y +CONFIG_NET_APP_SETTINGS=y +CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1" +CONFIG_ZTEST=y +#CONFIG_NET_DEBUG_APP=y +#CONFIG_SYS_LOG_NET_LEVEL=4 +#CONFIG_NET_SHELL=y diff --git a/tests/net/app/src/Makefile b/tests/net/app/src/Makefile new file mode 100644 index 0000000000000..cc0883fd51afe --- /dev/null +++ b/tests/net/app/src/Makefile @@ -0,0 +1,4 @@ +obj-y = main.o +ccflags-y += -I${ZEPHYR_BASE}/subsys/net/ip + +include $(ZEPHYR_BASE)/tests/Makefile.test diff --git a/tests/net/app/src/main.c b/tests/net/app/src/main.c new file mode 100644 index 0000000000000..6d57af31146ee --- /dev/null +++ b/tests/net/app/src/main.c @@ -0,0 +1,818 @@ +/* main.c - Application main entry point */ + +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#define NET_LOG_ENABLED 1 +#include "net_private.h" + +#if defined(CONFIG_NET_DEBUG_IF) +#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__) +#else +#define DBG(fmt, ...) +#endif + +#if defined(CONFIG_NET_IPV6) +/* Interface 1 addresses */ +static struct in6_addr my_addr1 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; + +/* Interface 2 addresses */ +static struct in6_addr my_addr2 = { { { 0x20, 0x01, 0x0d, 0xb8, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; + +/* Extra address is assigned to ll_addr */ +static struct in6_addr ll_addr = { { { 0xfe, 0x80, 0x43, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0xf2, 0xaa, 0x29, 0x02, + 0x04 } } }; + +static struct in6_addr in6addr_mcast = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0x1 } } }; +#endif + +#if defined(CONFIG_NET_IPV4) +/* Interface 1 addresses IPv4 */ +static struct in_addr my_addr4 = { { { 192, 0, 1, 1 } } }; +#endif + +static struct net_if *iface1; + +static bool test_failed; +static bool test_started; +static struct k_sem wait_data; + +#define WAIT_TIME 250 + +struct net_if_test { + u8_t idx; + u8_t mac_addr[sizeof(struct net_eth_addr)]; + struct net_linkaddr ll_addr; +}; + +static int net_iface_dev_init(struct device *dev) +{ + return 0; +} + +static u8_t *net_iface_get_mac(struct device *dev) +{ + struct net_if_test *data = dev->driver_data; + + if (data->mac_addr[2] == 0x00) { + /* 00-00-5E-00-53-xx Documentation RFC 7042 */ + data->mac_addr[0] = 0x00; + data->mac_addr[1] = 0x00; + data->mac_addr[2] = 0x5E; + data->mac_addr[3] = 0x00; + data->mac_addr[4] = 0x53; + data->mac_addr[5] = sys_rand32_get(); + } + + data->ll_addr.addr = data->mac_addr; + data->ll_addr.len = 6; + + return data->mac_addr; +} + +static void net_iface_init(struct net_if *iface) +{ + u8_t *mac = net_iface_get_mac(net_if_get_device(iface)); + + net_if_set_link_addr(iface, mac, sizeof(struct net_eth_addr), + NET_LINK_ETHERNET); +} + +static int sender_iface(struct net_if *iface, struct net_pkt *pkt) +{ + if (!pkt->frags) { + DBG("No data to send!\n"); + return -ENODATA; + } + + if (test_started) { + struct net_if_test *data = iface->dev->driver_data; + + DBG("Sending at iface %d %p\n", net_if_get_by_iface(iface), + iface); + + if (net_pkt_iface(pkt) != iface) { + DBG("Invalid interface %p, expecting %p\n", + net_pkt_iface(pkt), iface); + test_failed = true; + } + + if (net_if_get_by_iface(iface) != data->idx) { + DBG("Invalid interface %d index, expecting %d\n", + data->idx, net_if_get_by_iface(iface)); + test_failed = true; + } + } + + net_pkt_unref(pkt); + + k_sem_give(&wait_data); + + return 0; +} + +struct net_if_test net_iface1_data; + +static struct net_if_api net_iface_api = { + .init = net_iface_init, + .send = sender_iface, +}; + +#define _ETH_L2_LAYER DUMMY_L2 +#define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2) + +NET_DEVICE_INIT_INSTANCE(net_iface1_test, + "iface1", + iface1, + net_iface_dev_init, + &net_iface1_data, + NULL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, + &net_iface_api, + _ETH_L2_LAYER, + _ETH_L2_CTX_TYPE, + 127); + +static void iface_setup(void) +{ +#if defined(CONFIG_NET_IPV6) + struct net_if_mcast_addr *maddr; +#endif + struct net_if_addr *ifaddr; + int idx; + + /* The semaphore is there to wait the data to be received. */ + k_sem_init(&wait_data, 0, UINT_MAX); + + iface1 = net_if_get_by_index(0); + + ((struct net_if_test *)iface1->dev->driver_data)->idx = 0; + + idx = net_if_get_by_iface(iface1); + zassert_equal(idx, 0, "Invalid index iface1"); + + DBG("Interfaces: [%d] iface1 %p\n", + net_if_get_by_iface(iface1), iface1); + + zassert_not_null(iface1, "Interface 1"); + +#if defined(CONFIG_NET_IPV6) + ifaddr = net_if_ipv6_addr_add(iface1, &my_addr1, + NET_ADDR_MANUAL, 0); + if (!ifaddr) { + DBG("Cannot add IPv6 address %s\n", + net_sprint_ipv6_addr(&my_addr1)); + zassert_not_null(ifaddr, "addr1"); + } + + /* For testing purposes we need to set the adddresses preferred */ + ifaddr->addr_state = NET_ADDR_PREFERRED; + + ifaddr = net_if_ipv6_addr_add(iface1, &ll_addr, + NET_ADDR_MANUAL, 0); + if (!ifaddr) { + DBG("Cannot add IPv6 address %s\n", + net_sprint_ipv6_addr(&ll_addr)); + zassert_not_null(ifaddr, "ll_addr"); + } + + ifaddr->addr_state = NET_ADDR_PREFERRED; + + net_ipv6_addr_create(&in6addr_mcast, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001); + + maddr = net_if_ipv6_maddr_add(iface1, &in6addr_mcast); + if (!maddr) { + DBG("Cannot add multicast IPv6 address %s\n", + net_sprint_ipv6_addr(&in6addr_mcast)); + zassert_not_null(maddr, "mcast"); + } +#endif /* IPv6 */ + +#if defined(CONFIG_NET_IPV4) + ifaddr = net_if_ipv4_addr_add(iface1, &my_addr4, + NET_ADDR_MANUAL, 0); + if (!ifaddr) { + DBG("Cannot add IPv4 address %s\n", + net_sprint_ipv4_addr(&my_addr4)); + zassert_not_null(ifaddr, "addr4"); + } +#endif + + net_if_up(iface1); + + /* The interface might receive data which might fail the checks + * in the iface sending function, so we need to reset the failure + * flag. + */ + test_failed = false; + + test_started = true; +} + +static void app_init(void) +{ + int ret; + + ret = net_app_init("Test app", 0, 1); + zassert_equal(ret, 0, "app init"); +} + +static struct net_app_ctx udp_server_ctx; +static struct net_app_ctx tcp_server_ctx; + +static void app_udp_server_init(void) +{ + int ret; + + ret = net_app_init_udp_server(&udp_server_ctx, NULL, 42421, NULL); + zassert_equal(ret, 0, "UDP server init"); +} + +static void app_tcp_server_init(void) +{ + int ret; + + ret = net_app_init_tcp_server(&tcp_server_ctx, NULL, 42422, NULL); + zassert_equal(ret, 0, "TCP server init"); +} + +static void app_udp_server_listen(void) +{ + int ret; + + net_app_server_enable(&udp_server_ctx); + + ret = net_app_listen(&udp_server_ctx); + zassert_equal(ret, 0, "UDP listen failed"); +} + +static void app_tcp_server_listen(void) +{ + int ret; + + net_app_server_enable(&tcp_server_ctx); + + ret = net_app_listen(&tcp_server_ctx); + zassert_equal(ret, 0, "TCP listen failed"); +} + +static void app_tcp6_client_peer(void) +{ +#if defined(CONFIG_NET_IPV6) + static struct net_app_ctx ctx; + int port; + int ret; + + ret = net_app_init_tcp_client(&ctx, + NULL, + NULL, + "2001:db8:200::1", + 42422, + 0, + NULL); + zassert_equal(ret, 0, "TCP IPv6 client init"); + + port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port); + zassert_equal(port, 42422, "TCP port invalid"); + + ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr, + &my_addr2); + zassert_equal(ret, true, "IPv6 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "TCP IPv6 client close"); +#endif +} + +static void app_tcp4_client_peer(void) +{ +#if defined(CONFIG_NET_IPV4) + static struct net_app_ctx ctx; + int port; + int ret; + + ret = net_app_init_tcp_client(&ctx, + NULL, + NULL, + "192.0.1.1", + 42422, + 0, + NULL); + zassert_equal(ret, 0, "TCP IPv4 client init"); + + port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port); + zassert_equal(port, 42422, "TCP port invalid"); + + ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr, + &my_addr4); + zassert_equal(ret, true, "IPv4 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "TCP IPv4 client close"); +#endif +} + +static void app_udp6_client_peer(void) +{ +#if defined(CONFIG_NET_IPV6) + static struct net_app_ctx ctx; + int port; + int ret; + + ret = net_app_init_udp_client(&ctx, + NULL, + NULL, + "2001:db8:200::1", + 42421, + 0, + NULL); + zassert_equal(ret, 0, "UDP IPv6 client init"); + + port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port); + zassert_equal(port, 42421, "UDP port invalid"); + + ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr, + &my_addr2); + zassert_equal(ret, true, "IPv6 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "UDP IPv6 client close"); +#endif +} + +static void app_udp4_client_peer(void) +{ +#if defined(CONFIG_NET_IPV4) + static struct net_app_ctx ctx; + int port; + int ret; + + ret = net_app_init_udp_client(&ctx, + NULL, + NULL, + "192.0.1.1", + 42421, + 0, + NULL); + zassert_equal(ret, 0, "TCP IPv4 client init"); + + port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port); + zassert_equal(port, 42421, "UDP port invalid"); + + ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr, + &my_addr4); + zassert_equal(ret, true, "IPv4 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "UDP IPv4 client close"); +#endif +} + +static void app_tcp6_client_peer_with_port(void) +{ +#if defined(CONFIG_NET_IPV6) + static struct net_app_ctx ctx; + int port; + int ret; + + ret = net_app_init_tcp_client(&ctx, + NULL, + NULL, + "[2001:db8:200::1]:1234", + 42422, + 0, + NULL); + zassert_equal(ret, 0, "TCP IPv6 client init"); + + port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port); + zassert_equal(port, 1234, "TCP port invalid"); + + ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr, + &my_addr2); + zassert_equal(ret, true, "IPv6 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "TCP IPv6 client close"); +#endif +} + +static void app_tcp4_client_peer_with_port(void) +{ +#if defined(CONFIG_NET_IPV4) + static struct net_app_ctx ctx; + int port; + int ret; + + ret = net_app_init_tcp_client(&ctx, + NULL, + NULL, + "192.0.1.1:1234", + 42422, + 0, + NULL); + zassert_equal(ret, 0, "TCP IPv4 client init"); + + port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port); + zassert_equal(port, 1234, "TCP port invalid"); + + ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr, + &my_addr4); + zassert_equal(ret, true, "IPv4 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "TCP IPv4 client close"); +#endif +} + +static void app_udp6_client_peer_with_port(void) +{ +#if defined(CONFIG_NET_IPV6) + static struct net_app_ctx ctx; + int port; + int ret; + + ret = net_app_init_udp_client(&ctx, + NULL, + NULL, + "[2001:db8:200::1]:9999", + 42421, + 0, + NULL); + zassert_equal(ret, 0, "UDP IPv6 client init"); + + port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port); + zassert_equal(port, 9999, "UDP port invalid"); + + ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr, + &my_addr2); + zassert_equal(ret, true, "IPv6 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "UDP IPv6 client close"); +#endif +} + +static void app_udp4_client_peer_with_port(void) +{ +#if defined(CONFIG_NET_IPV4) + static struct net_app_ctx ctx; + int port; + int ret; + + ret = net_app_init_udp_client(&ctx, + NULL, + NULL, + "192.0.1.1:9999", + 42421, + 0, + NULL); + zassert_equal(ret, 0, "TCP IPv4 client init"); + + port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port); + zassert_equal(port, 9999, "UDP port invalid"); + + ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr, + &my_addr4); + zassert_equal(ret, true, "IPv4 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "UDP IPv4 client close"); +#endif +} + +static void app_tcp6_client_peer_addr(void) +{ +#if defined(CONFIG_NET_IPV6) + static struct net_app_ctx ctx; + struct sockaddr_in6 peer; + int port; + int ret; + + net_ipaddr_copy(&peer.sin6_addr, &my_addr2); + peer.sin6_port = htons(8765); + peer.sin6_family = AF_INET6; + + ret = net_app_init_tcp_client(&ctx, + NULL, + (struct sockaddr *)&peer, + "foobar", + 42422, + 0, + NULL); + zassert_equal(ret, 0, "TCP IPv6 client init"); + + port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port); + zassert_equal(port, 8765, "TCP port invalid"); + + ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr, + &my_addr2); + zassert_equal(ret, true, "IPv6 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "TCP IPv6 client close"); +#endif +} + +static void app_tcp4_client_peer_addr(void) +{ +#if defined(CONFIG_NET_IPV4) + static struct net_app_ctx ctx; + struct sockaddr_in peer; + int port; + int ret; + + net_ipaddr_copy(&peer.sin_addr, &my_addr4); + peer.sin_port = htons(8765); + peer.sin_family = AF_INET; + + ret = net_app_init_tcp_client(&ctx, + NULL, + (struct sockaddr *)&peer, + "foobar", + 42422, + 0, + NULL); + zassert_equal(ret, 0, "TCP IPv4 client init"); + + port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port); + zassert_equal(port, 8765, "TCP port invalid"); + + ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr, + &my_addr4); + zassert_equal(ret, true, "IPv4 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "TCP IPv4 client close"); +#endif +} + +static void app_udp6_client_peer_addr(void) +{ +#if defined(CONFIG_NET_IPV6) + static struct net_app_ctx ctx; + struct sockaddr_in6 peer; + int port; + int ret; + + net_ipaddr_copy(&peer.sin6_addr, &my_addr2); + peer.sin6_port = htons(8765); + peer.sin6_family = AF_INET6; + + ret = net_app_init_udp_client(&ctx, + NULL, + (struct sockaddr *)&peer, + "foobar", + 42422, + 0, + NULL); + zassert_equal(ret, 0, "UDP IPv6 client init"); + + port = ntohs(net_sin6(&ctx.ipv6.remote)->sin6_port); + zassert_equal(port, 8765, "UDP port invalid"); + + ret = net_ipv6_addr_cmp(&net_sin6(&ctx.ipv6.remote)->sin6_addr, + &my_addr2); + zassert_equal(ret, true, "IPv6 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "UDP IPv6 client close"); +#endif +} + +static void app_udp4_client_peer_addr(void) +{ +#if defined(CONFIG_NET_IPV4) + static struct net_app_ctx ctx; + struct sockaddr_in peer; + int port; + int ret; + + net_ipaddr_copy(&peer.sin_addr, &my_addr4); + peer.sin_port = htons(8765); + peer.sin_family = AF_INET; + + ret = net_app_init_udp_client(&ctx, + NULL, + (struct sockaddr *)&peer, + "foobar", + 42422, + 0, + NULL); + zassert_equal(ret, 0, "UDP IPv4 client init"); + + port = ntohs(net_sin(&ctx.ipv4.remote)->sin_port); + zassert_equal(port, 8765, "UDP port invalid"); + + ret = net_ipv4_addr_cmp(&net_sin(&ctx.ipv4.remote)->sin_addr, + &my_addr4); + zassert_equal(ret, true, "IPv4 address mismatch"); + + ret = net_app_close(&ctx); + zassert_equal(ret, 0, "UDP IPv4 client close"); +#endif +} + +static void app_tcp6_client_hostname_fail(void) +{ +#if defined(CONFIG_NET_IPV6) + static struct net_app_ctx ctx; + int ret; + + ret = net_app_init_tcp_client(&ctx, + NULL, + NULL, + "foobar", + 42422, + 0, + NULL); + zassert_equal(ret, -EINVAL, "TCP IPv6 client init"); +#endif +} + +static void app_tcp4_client_hostname_fail(void) +{ +#if defined(CONFIG_NET_IPV4) + static struct net_app_ctx ctx; + int ret; + + ret = net_app_init_tcp_client(&ctx, + NULL, + NULL, + "foobar", + 42422, + 0, + NULL); + zassert_equal(ret, -EINVAL, "TCP IPv4 client init"); +#endif +} + +static void app_udp6_client_hostname_fail(void) +{ +#if defined(CONFIG_NET_IPV6) + static struct net_app_ctx ctx; + int ret; + + ret = net_app_init_udp_client(&ctx, + NULL, + NULL, + "foobar", + 42422, + 0, + NULL); + zassert_equal(ret, -EINVAL, "UDP IPv6 client init"); +#endif +} + +static void app_udp4_client_hostname_fail(void) +{ +#if defined(CONFIG_NET_IPV4) + static struct net_app_ctx ctx; + int ret; + + ret = net_app_init_udp_client(&ctx, + NULL, + NULL, + "foobar", + 42422, + 0, + NULL); + zassert_equal(ret, -EINVAL, "UDP IPv4 client init"); +#endif +} + +static void app_tcp6_client_hostname(void) +{ +#if defined(CONFIG_NET_IPV6) && defined(CONFIG_DNS_RESOLVER) + static struct net_app_ctx ctx; + int ret; + + ret = net_app_init_tcp_client(&ctx, + NULL, + NULL, + "foobar", + 42422, + MSEC(100), + NULL); + zassert_equal(ret, -ETIMEDOUT, "TCP IPv6 client init"); +#endif +} + +static void app_tcp4_client_hostname(void) +{ +#if defined(CONFIG_NET_IPV4) && defined(CONFIG_DNS_RESOLVER) + static struct net_app_ctx ctx; + int ret; + + ret = net_app_init_tcp_client(&ctx, + NULL, + NULL, + "foobar", + 42422, + MSEC(100), + NULL); + zassert_equal(ret, -ETIMEDOUT, "TCP IPv4 client init"); +#endif +} + +static void app_udp6_client_hostname(void) +{ +#if defined(CONFIG_NET_IPV6) && defined(CONFIG_DNS_RESOLVER) + static struct net_app_ctx ctx; + int ret; + + ret = net_app_init_udp_client(&ctx, + NULL, + NULL, + "foobar", + 42422, + MSEC(100), + NULL); + zassert_equal(ret, -ETIMEDOUT, "UDP IPv6 client init"); +#endif +} + +static void app_udp4_client_hostname(void) +{ +#if defined(CONFIG_NET_IPV4) && defined(CONFIG_DNS_RESOLVER) + static struct net_app_ctx ctx; + int ret; + + ret = net_app_init_udp_client(&ctx, + NULL, + NULL, + "foobar", + 42422, + MSEC(100), + NULL); + zassert_equal(ret, -ETIMEDOUT, "UDP IPv4 client init"); +#endif +} + +static void app_close_server(void) +{ + int ret; + + ret = net_app_close(&udp_server_ctx); + zassert_equal(ret, 0, "UDP server close"); + + ret = net_app_close(&tcp_server_ctx); + zassert_equal(ret, 0, "TCP server close"); +} + +void test_main(void) +{ + ztest_test_suite(net_app_test, + ztest_unit_test(iface_setup), + ztest_unit_test(app_init), + ztest_unit_test(app_udp_server_init), + ztest_unit_test(app_tcp_server_init), + ztest_unit_test(app_udp_server_listen), + ztest_unit_test(app_tcp_server_listen), + ztest_unit_test(app_tcp6_client_peer), + ztest_unit_test(app_udp6_client_peer), + ztest_unit_test(app_tcp4_client_peer), + ztest_unit_test(app_udp4_client_peer), + ztest_unit_test(app_tcp6_client_peer_with_port), + ztest_unit_test(app_tcp4_client_peer_with_port), + ztest_unit_test(app_udp6_client_peer_with_port), + ztest_unit_test(app_udp4_client_peer_with_port), + ztest_unit_test(app_tcp6_client_peer_addr), + ztest_unit_test(app_tcp4_client_peer_addr), + ztest_unit_test(app_udp6_client_peer_addr), + ztest_unit_test(app_udp4_client_peer_addr), + ztest_unit_test(app_tcp6_client_hostname_fail), + ztest_unit_test(app_tcp4_client_hostname_fail), + ztest_unit_test(app_udp6_client_hostname_fail), + ztest_unit_test(app_udp4_client_hostname_fail), + ztest_unit_test(app_tcp6_client_hostname), + ztest_unit_test(app_tcp4_client_hostname), + ztest_unit_test(app_udp6_client_hostname), + ztest_unit_test(app_udp4_client_hostname), + ztest_unit_test(app_close_server) + ); + + ztest_run_test_suite(net_app_test); +} diff --git a/tests/net/app/testcase.yaml b/tests/net/app/testcase.yaml new file mode 100644 index 0000000000000..e1a7e1cb6fb3c --- /dev/null +++ b/tests/net/app/testcase.yaml @@ -0,0 +1,16 @@ +tests: + - test: + min_ram: 32 + tags: net + - test-no-ipv6: + extra_args: CONF_FILE=prj-no-ipv6.conf + min_ram: 32 + tags: net + - test-no-ipv4: + extra_args: CONF_FILE=prj-no-ipv4.conf + min_ram: 32 + tags: net + - test-with-dns: + extra_args: CONF_FILE=prj-with-dns.conf + min_ram: 32 + tags: net dns