From e054817424ee88984f1c6a93c3d547d69ccbaf65 Mon Sep 17 00:00:00 2001 From: pillip Date: Tue, 12 Oct 2021 19:48:35 +0900 Subject: [PATCH] apps/nettest: add network test add network test getaddrinfo, gethostbyname, getnameinfo... --- apps/examples/nettest/Makefile | 2 +- apps/examples/nettest/nettest.c | 12 +- apps/examples/nettest/test_main.c | 264 ++++++++++++++++++++++++ apps/system/utils/netcmd_netmon.c | 9 +- external/include/netutils/netlib.h | 2 +- external/include/stress_tool/st_perf.h | 1 + external/netutils/netlib_netmon.c | 20 +- external/netutils/netlib_setdnsserver.c | 7 +- external/stress_tool/st_perf.c | 4 +- lib/libc/netdb/lib_getaddrinfo.c | 9 +- os/net/lwip/src/include/lwip/lwipopts.h | 3 +- os/net/netmgr/netmgr_ioctl_lwip.c | 4 +- 12 files changed, 307 insertions(+), 30 deletions(-) create mode 100644 apps/examples/nettest/test_main.c diff --git a/apps/examples/nettest/Makefile b/apps/examples/nettest/Makefile index a6ebdfe011..ed49d424e6 100644 --- a/apps/examples/nettest/Makefile +++ b/apps/examples/nettest/Makefile @@ -63,7 +63,7 @@ THREADEXEC = TASH_EXECMD_ASYNC # transport layer (TCP / UDP) / IP multicast functionality test example ASRCS = -CSRCS = nettest_stress.c +CSRCS = nettest_stress.c test_main.c MAINSRC = nettest.c AOBJS = $(ASRCS:.S=$(OBJEXT)) diff --git a/apps/examples/nettest/nettest.c b/apps/examples/nettest/nettest.c index 8693555cd6..cd6fb6e1ff 100644 --- a/apps/examples/nettest/nettest.c +++ b/apps/examples/nettest/nettest.c @@ -144,6 +144,7 @@ uint32_t total_data; #define NETTEST_SERVER_MODE 1 #define NETTEST_CLIENT_MODE 2 +#define NETTEST_INTERNAL_MODE 3 #define NETTEST_PROTO_TCP "tcp" #define NETTEST_PROTO_UDP "udp" #define NETTEST_PROTO_BROADCAST "brc" @@ -170,6 +171,7 @@ static void show_usage(void) printf("MODE:\n"); printf("\t1: server\n"); printf("\t2: client\n"); + printf("\t3: internal\n"); printf("PROTOCOL\n"); printf("\ttcp: TCP\n"); @@ -477,7 +479,7 @@ void ipmcast_receiver_thread(int num_packets, const char *intf) printf("[MCASTSERV] fail: adding multicast group %d\n", errno); goto out_with_socket; } - + if (bind(sd, (struct sockaddr *)&localSock, sizeof(localSock))) { printf("[MCASTSERV] ERR: binding datagram socket\n"); goto out_with_socket; @@ -832,6 +834,7 @@ void tcp_client_thread(int num_packets, uint32_t sleep_time) } extern void nettest_stress(char *addr, int port); +extern int network_internal_test(void); /* Sample App to test Transport Layer (TCP / UDP) / IP Multicast Functionality */ #ifdef CONFIG_BUILD_KERNEL @@ -847,12 +850,16 @@ int nettest_main(int argc, char *argv[]) /* pps - packet per second, default value 1 */ uint32_t pps = 1; + if (argc == 2 && atoi(argv[1]) == NETTEST_INTERNAL_MODE) { + network_internal_test(); + return 0; + } if (argc < 5) { goto err_with_input; } mode = atoi(argv[1]); - if (mode != NETTEST_SERVER_MODE && mode != NETTEST_CLIENT_MODE) { + if (mode != NETTEST_SERVER_MODE && mode != NETTEST_CLIENT_MODE && mode != NETTEST_INTERNAL_MODE) { goto err_with_input; } @@ -930,4 +937,3 @@ int nettest_main(int argc, char *argv[]) show_usage(); return -1; } - diff --git a/apps/examples/nettest/test_main.c b/apps/examples/nettest/test_main.c new file mode 100644 index 0000000000..823789c6e2 --- /dev/null +++ b/apps/examples/nettest/test_main.c @@ -0,0 +1,264 @@ +/**************************************************************************** + * + * Copyright 2021 Samsung Electronics All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + * + ****************************************************************************/ +#include +#include +#include +#include + +#define NT_TEST_TRIAL 2 +#define NT_MAXHOST 1024 /* refer NI_MAXHOST */ +#define NT_MAXSERV 64 /* refer tmpserv in lwip_getnameinfo */ +#define TC_HOST_NAME "www.google.com" +#define TC_SERVICE "80" +#define NT_STR_DNS_ADDR "8.8.8.8" + +char g_hostname[NT_MAXHOST]; // stack overflow can be happened if set this value local variable. +char g_serv[NT_MAXSERV]; + +static void _print_addrinfo(struct addrinfo *addr) +{ + struct addrinfo *rp; + char buf[64]; + printf("=====================================\n"); + printf("family\tsocket type\tprotocol\taddress\n"); + printf("-------------------------------------\n"); + for (rp = addr; rp != NULL; rp = rp->ai_next) { + printf("%d\t%d\t%d\t", rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (rp->ai_family == AF_INET) { + inet_ntop(rp->ai_family, &(((struct sockaddr_in *)(rp->ai_addr))->sin_addr), buf, sizeof(buf)); + printf("%s\n", buf); + } else if (rp->ai_family == AF_INET6) { + inet_ntop(rp->ai_family, &(((struct sockaddr_in6 *)(rp->ai_addr))->sin6_addr), buf, sizeof(buf)); + printf("%s\n", buf); + } else { + printf("\n"); + } + } + printf("=====================================\n\n"); +} + +static void _print_serv_info(const char *host, const char *service) +{ + printf("=====================================\n"); + printf("host\tservice\n"); + printf("-------------------------------------\n"); + printf("%s\t%s\n", host, service); + printf("=====================================\n\n"); +} + +static void _print_host(const struct hostent *he) +{ + struct in_addr **addr_list; + printf("=====================================\n"); + printf("Official name is: %s\n", he->h_name); + printf("IP address: %s\n", inet_ntoa(*(struct in_addr *)he->h_addr)); + printf("All addresses: "); + addr_list = (struct in_addr **)he->h_addr_list; + for (int i = 0; addr_list[i] != NULL; i++) { + printf("%s ", inet_ntoa(*addr_list[i])); + } + printf("\n=====================================\n\n"); +} + +/* + * Description: get socket information + */ +START_TEST_F(getaddrinfo_p) +{ + struct addrinfo hints; + struct addrinfo *servinfo; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + int res = getaddrinfo(TC_HOST_NAME, TC_SERVICE, &hints, &servinfo); + ST_EXPECT_EQ(0, res); + if (res == 0) { + _print_addrinfo(servinfo); + freeaddrinfo(servinfo); + } +} +END_TEST_F + +/* + * Description: verify getaddrinfo negative case + */ +START_TEST_F(getaddrinfo_n) +{ + ST_EXPECT_NEQ(0, getaddrinfo(NULL, NULL, NULL, NULL)); +} +END_TEST_F + +/* + * description: getnameinfo positive + */ +START_TEST_F(getnameinfo_p) +{ + struct addrinfo hints; + struct addrinfo *servinfo; + int res = 0; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + res = getaddrinfo(TC_HOST_NAME, TC_SERVICE, &hints, &servinfo); + ST_EXPECT_EQ(0, res); + + res = getnameinfo(servinfo->ai_addr, sizeof(struct sockaddr), + g_hostname, sizeof(g_hostname), + g_serv, sizeof(g_serv), + NI_NUMERICSERV | NI_NUMERICHOST); + ST_EXPECT_EQ(0, res); + if (res == 0) { + _print_serv_info(g_hostname, g_serv); + } + freeaddrinfo(servinfo); +} +END_TEST_F + +/* + * description: getnameinfo negative + */ +START_TEST_F(getnameinfo_n) +{ + int res = getnameinfo(NULL, 0, + g_hostname, sizeof(g_hostname), + g_serv, sizeof(g_serv), + NI_NUMERICSERV | NI_NUMERICHOST); + ST_EXPECT_NEQ(0, res); +} +END_TEST_F + +/* + * description: gethostbyname positive + */ +START_TEST_F(gethostbyname_p) +{ + struct hostent *shost; + shost = gethostbyname(TC_HOST_NAME); + ST_EXPECT_NEQ(NULL, shost); + if (shost != NULL) { + _print_host(shost); + } +} +END_TEST_F + +/* + * description: gethostbyname negative + */ +START_TEST_F(gethostbyname_n) +{ + struct hostent *shost; + shost = gethostbyname(NULL); + ST_EXPECT_EQ(NULL, shost); +} +END_TEST_F + +/* + * description: get socket information + */ +START_TEST_F(netmon_sock) +{ + char *str_sock = NULL; + int ret = netlib_netmon_sock(str_sock); + ST_EXPECT_EQ(0, ret); + if (ret == 0) { + printf("%s\n", str_sock); + free(str_sock); + } +} +END_TEST_F + +/* + * description: get network stack statistics info + */ +START_TEST_F(netmon_stats) +{ + char *str_stats = NULL; + int ret = netlib_getstats((void *)str_stats); + ST_EXPECT_EQ(0, ret); + if (ret == 0) { + printf("%s\n", str_stats); + free(str_stats); + } +} +END_TEST_F + +/* + * Description: get NIC statistics + */ +START_TEST_F(netmon_dev_stats) +{ + char *str_stats = NULL; + int ret = netlib_netmon_devstats("wlan0", (void **)&str_stats); + ST_EXPECT_EQ(0, ret); + if (ret == 0) { + printf("%s\n", str_stats); + free(str_stats); + } +} +END_TEST_F + +/* + * description: set dns server + */ +START_TEST_F(set_dns_p) +{ + struct sockaddr_in dns_addr; + memset(&dns_addr, 0x0, sizeof(struct sockaddr_in)); + dns_addr.sin_family = AF_INET; + inet_pton(AF_INET, NT_STR_DNS_ADDR, (void *)&dns_addr.sin_addr); + int res = netlib_setdnsserver((struct sockaddr *)&dns_addr, -1); + ST_EXPECT_EQ(0, res); +} +END_TEST_F + +/* + * description: set dns server negative + */ +START_TEST_F(set_dns_n) +{ + int res = netlib_setdnsserver(NULL, -1); + ST_EXPECT_NEQ(0, res); +} +END_TEST_F + +int network_internal_test(void) +{ + ST_SET_PACK(nettest); + + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "getaddrinfo p", getaddrinfo_p); + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "getaddrinfo n", getaddrinfo_n); + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "gethostbyname p", gethostbyname_p); + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "gethostbyname n", gethostbyname_n); + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "getnameinfo p", getnameinfo_p); + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "getnameinfo n", getnameinfo_n); + + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "get sock info from netmon", netmon_sock); + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "get statistics from netmon", netmon_stats); + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "get NIC statistics", netmon_dev_stats); + + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "set dns positive", set_dns_p); + ST_SET_SMOKE1(nettest, NT_TEST_TRIAL, ST_NO_TIMELIMIT, "set dns negative", set_dns_n); + + ST_RUN_TEST(nettest); + ST_RESULT_TEST(nettest); + + return 0; +} diff --git a/apps/system/utils/netcmd_netmon.c b/apps/system/utils/netcmd_netmon.c index bcc94d9771..40ac9651d7 100644 --- a/apps/system/utils/netcmd_netmon.c +++ b/apps/system/utils/netcmd_netmon.c @@ -100,11 +100,11 @@ int cmd_netmon(int argc, char **argv) /* Get socket information: SIOCGETSOCK */ char *buf = NULL; ret = netlib_netmon_sock(buf); - if (ret != 0) { - NETCMD_LOGE(NTAG, "Failed to fetch socket info.\n"); - } else { + if (!ret) { _print_sock(buf); free(buf); + } else { + NETCMD_LOGE(NTAG, "Failed to fetch socket info.\n"); } } else if (!(strncmp(argv[1], "wifi", strlen("wifi") + 1))) { return _print_wifi_info(); @@ -112,9 +112,10 @@ int cmd_netmon(int argc, char **argv) return -1; } else { char *buf = NULL; - ret = netlib_netmon_devstats(argv[1], buf); + ret = netlib_netmon_devstats(argv[1], (void **)&buf); if (!ret) { _print_devstats(buf); + free(buf); } else { NETCMD_LOGE(NTAG, "No device interface %s\n", argv[1]); return ERROR; diff --git a/external/include/netutils/netlib.h b/external/include/netutils/netlib.h index 3fd6d45379..981baa0476 100644 --- a/external/include/netutils/netlib.h +++ b/external/include/netutils/netlib.h @@ -154,7 +154,7 @@ void netlib_freeifaddrs(struct ifaddrs *ifa); #ifdef CONFIG_NET_NETMON int netlib_netmon_sock(void *arg); -int netlib_netmon_devstats(const char *ifname, void *arg); +int netlib_netmon_devstats(const char *ifname, void **arg); #endif /* HTTP support */ diff --git a/external/include/stress_tool/st_perf.h b/external/include/stress_tool/st_perf.h index 18d7e05c4b..5fb3a19892 100644 --- a/external/include/stress_tool/st_perf.h +++ b/external/include/stress_tool/st_perf.h @@ -38,6 +38,7 @@ #define ST_ELOG printf #endif +#define ST_NO_TIMELIMIT 0 /* * Initializer Macro */ diff --git a/external/netutils/netlib_netmon.c b/external/netutils/netlib_netmon.c index f4c6607cb6..6031dbe47b 100644 --- a/external/netutils/netlib_netmon.c +++ b/external/netutils/netlib_netmon.c @@ -22,10 +22,11 @@ #include #if defined(CONFIG_NET) && (CONFIG_NSOCKET_DESCRIPTORS > 0) + +#include #include #include #include -#include #include #include #include @@ -33,6 +34,8 @@ #include #include +#define TAG "[NETLIB]" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -59,7 +62,7 @@ int netlib_netmon_sock(void *arg) struct req_lwip_data req; int sockfd = socket(AF_INET, NETLIB_SOCK_IOCTL, 0); if (sockfd == -1) { - NET_LOGE("socket() failed with errno: %d\n", errno); + NET_LOGE(TAG, "socket() failed with errno: %d\n", errno); return -1; } @@ -69,7 +72,7 @@ int netlib_netmon_sock(void *arg) ret = ioctl(sockfd, SIOCLWIP, (unsigned long)&req); close(sockfd); if (ret == ERROR) { - NET_LOGE("ioctl() failed with errno: %d\n", errno); + NET_LOGE(TAG, "ioctl() failed with errno: %d\n", errno); return -1; } arg = (void *)req.msg.netmon.info; @@ -93,7 +96,7 @@ int netlib_netmon_sock(void *arg) * ****************************************************************************/ -int netlib_netmon_devstats(const char *ifname, void *arg) +int netlib_netmon_devstats(const char *ifname, void **arg) { if (ifname == NULL || arg == NULL) { return -1; @@ -102,7 +105,7 @@ int netlib_netmon_devstats(const char *ifname, void *arg) struct req_lwip_data req; int sockfd = socket(AF_INET, NETLIB_SOCK_IOCTL, 0); if (sockfd == -1) { - NET_LOGE("socket() failed with errno: %d\n", errno); + NET_LOGE(TAG, "socket() failed with errno: %d\n", errno); return -1; } @@ -113,10 +116,13 @@ int netlib_netmon_devstats(const char *ifname, void *arg) ret = ioctl(sockfd, SIOCLWIP, (unsigned long)&req); close(sockfd); if (ret == ERROR) { - NET_LOGE("ioctl() failed with errno: %d\n", errno); + NET_LOGE(TAG, "ioctl() failed with errno: %d\n", errno); return -1; } - arg = (void *)req.msg.netmon.info; + ret = req.req_res; + if (ret == 0) { + *arg = (void *)req.msg.netmon.info; + } return req.req_res; } #endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS */ diff --git a/external/netutils/netlib_setdnsserver.c b/external/netutils/netlib_setdnsserver.c index 9b61188624..dd93564d43 100644 --- a/external/netutils/netlib_setdnsserver.c +++ b/external/netutils/netlib_setdnsserver.c @@ -51,9 +51,9 @@ * EBADF * 'fd' is not a valid descriptor. * EFAULT - * 'arg' references an inaccessible memory area. + * 'addr' references an inaccessible memory area. * EINVAL - * 'cmd' or 'arg' is not valid. + * 'addr' or 'index' is not valid. * ENOTTY * 'fd' is not associated with a character special device. * ENOTTY @@ -67,6 +67,9 @@ int netlib_setdnsserver(struct sockaddr *addr, int index) { + if (!addr) { + return -1; + } int ret = -1; struct req_lwip_data req; diff --git a/external/stress_tool/st_perf.c b/external/stress_tool/st_perf.c index 6966573fe5..f7054ae882 100644 --- a/external/stress_tool/st_perf.c +++ b/external/stress_tool/st_perf.c @@ -175,10 +175,10 @@ void _print_performance(st_performance *perf) st_performance_stat *p = &perf->stat; if (p->result == STRESS_TC_PASS) { printf(" %-11d%-8d%-8d%-8d%-8d:SUCCESS\n", - p->count, p->max/1000, p->min/1000, p->sum/1000, p->fail); + p->count, p->max / 1000, p->min / 1000, p->sum / 1000, p->fail); } else { printf(" %-11d%-8d%-8d%-8d%-8d:FAILURE\n", - p->count, p->max/1000, p->min/1000, p->sum/1000, p->fail); + p->count, p->max / 1000, p->min / 1000, p->sum / 1000, p->fail); } } diff --git a/lib/libc/netdb/lib_getaddrinfo.c b/lib/libc/netdb/lib_getaddrinfo.c index c531f58ee7..33d29814ac 100644 --- a/lib/libc/netdb/lib_getaddrinfo.c +++ b/lib/libc/netdb/lib_getaddrinfo.c @@ -60,7 +60,6 @@ /**************************************************************************** * Name: getaddrinfo ****************************************************************************/ -#ifdef CONFIG_NET_LWIP_NETDB int getaddrinfo(FAR const char *hostname, FAR const char *servname, FAR const struct addrinfo *hint, @@ -83,15 +82,15 @@ int getaddrinfo(FAR const char *hostname, req.msg.netdb.ai_res = NULL; ret = ioctl(sockfd, SIOCLWIP, (unsigned long)&req); + close(sockfd); if (ret == ERROR) { printf("ioctl() failed with errno: %d\n", errno); - close(sockfd); return ret; } ret = req.req_res; - *res = (struct addrinfo *)req.msg.netdb.ai_res; - close(sockfd); + if (ret == 0) { + *res = (struct addrinfo *)req.msg.netdb.ai_res; + } return ret; } -#endif diff --git a/os/net/lwip/src/include/lwip/lwipopts.h b/os/net/lwip/src/include/lwip/lwipopts.h index cbd25703a7..6fdd2af37f 100644 --- a/os/net/lwip/src/include/lwip/lwipopts.h +++ b/os/net/lwip/src/include/lwip/lwipopts.h @@ -1045,7 +1045,6 @@ /* ---------- Debug options ---------- */ /* ---------- Stat options ---------- */ - #ifdef CONFIG_NET_STATS #define LWIP_STATS CONFIG_NET_STATS #endif @@ -1093,7 +1092,7 @@ #ifdef CONFIG_NET_UDP_STATS #define UDP_STATS CONFIG_NET_UDP_STATS #else -#define IGMP_STATS +#define UDP_STATS 0 #endif #ifdef CONFIG_NET_TCP_STATS diff --git a/os/net/netmgr/netmgr_ioctl_lwip.c b/os/net/netmgr/netmgr_ioctl_lwip.c index 476a20373b..7e74ea4b02 100644 --- a/os/net/netmgr/netmgr_ioctl_lwip.c +++ b/os/net/netmgr/netmgr_ioctl_lwip.c @@ -15,7 +15,6 @@ * language governing permissions and limitations under the License. * ****************************************************************************/ - #include #include @@ -339,17 +338,16 @@ static int lwip_func_ioctl(int s, int cmd, void *arg) switch (req->type) { #if LWIP_DNS case GETADDRINFO: + ret = OK; /* req->req_res stores return value. So doesn't need to set ret */ req->req_res = lwip_getaddrinfo(req->msg.netdb.host_name, req->msg.netdb.serv_name, req->msg.netdb.ai_hint, &res); if (req->req_res != 0) { NET_LOGE(TAG, "lwip_getaddrinfo() returned with the error code: %d\n", ret); req->msg.netdb.ai_res = NULL; - ret = -EINVAL; } else { req->msg.netdb.ai_res = _netdev_copy_addrinfo(res); lwip_freeaddrinfo(res); - ret = OK; } break; case FREEADDRINFO: