diff options
author | satish.karunanithi <satish.fdio@gmail.com> | 2018-08-13 19:39:55 +0530 |
---|---|---|
committer | satish.karunanithi <satish.fdio@gmail.com> | 2018-08-14 10:22:59 +0530 |
commit | 54f5a270c74c405d3bb0e15d5b69d6d0e1e96c49 (patch) | |
tree | a855ebf120dd46c50784c30a53a1bdf9aedea632 /stacks/lwip_stack/tools | |
parent | bd6e75c243db1b384ba0882ecaf9063ec4cd70bd (diff) |
Feat : LWIP integration part3
Change-Id: I62998963da110827a410287eed90a22da7ae4222
Signed-off-by: satish.karunanithi <satish.fdio@gmail.com>
Diffstat (limited to 'stacks/lwip_stack/tools')
-rw-r--r-- | stacks/lwip_stack/tools/CMakeLists.txt | 91 | ||||
-rw-r--r-- | stacks/lwip_stack/tools/nping.c | 627 | ||||
-rw-r--r-- | stacks/lwip_stack/tools/ntcpdump.c | 1368 | ||||
-rw-r--r-- | stacks/lwip_stack/tools/tool_common.h | 243 |
4 files changed, 2329 insertions, 0 deletions
diff --git a/stacks/lwip_stack/tools/CMakeLists.txt b/stacks/lwip_stack/tools/CMakeLists.txt new file mode 100644 index 0000000..cfb5615 --- /dev/null +++ b/stacks/lwip_stack/tools/CMakeLists.txt @@ -0,0 +1,91 @@ +######################################################################### +# +# Copyright (c) 2018 Huawei Technologies Co.,Ltd. +# 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. +######################################################################### + +if(WITH_HAL_LIB) +else() +endif() +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${NSTACKTOOLS_PATH}) +LINK_DIRECTORIES(${LIB_PATH_SHARED} ${LIB_PATH_STATIC}) +INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/platform/SecureC/include/) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g -fPIC -fPIE -pie -m64 -mssse3 -std=gnu89") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wshadow -Wfloat-equal -Wformat=2") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector -fstack-protector-all") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,relro,-z,now -Wl,--disable-new-dtags,--rpath,.") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack -mcmodel=medium") + +INCLUDE_DIRECTORIES( + ../src/include/ + ../../../thirdparty/glog/glog-0.3.4/src/ + ../../SecureC/include/ +) + +#ADD_EXECUTABLE(narp narp.c) +#ADD_EXECUTABLE(nnetstat nnetstat.c) + +ADD_EXECUTABLE(ntcpdump ntcpdump.c) +if(WITH_SECUREC_LIB) +TARGET_LINK_LIBRARIES( + ntcpdump + pthread + rt + securec + -Wl,--whole-archive + libjson-c.a + libglog.a + dmm_api + -Wl,--no-whole-archive,-lstdc++ -ldl + rte_eal + rte_mempool + rte_mbuf + rte_ring +) +else() +TARGET_LINK_LIBRARIES( + ntcpdump + pthread + rt + -Wl,--whole-archive + libjson-c.a + libglog.a + dmm_api + -Wl,--no-whole-archive,-lstdc++ -ldl + rte_eal + rte_mempool + rte_mbuf + rte_ring +) +endif() + +if(WITH_SECUREC_LIB) +ADD_DEPENDENCIES(ntcpdump JSON GLOG SECUREC DPDK) +else() +ADD_DEPENDENCIES(ntcpdump JSON GLOG DPDK) +endif() + + +ADD_EXECUTABLE(nping nping.c) + +if(WITH_SECUREC_LIB) +ADD_DEPENDENCIES(nping SECUREC DPDK) +else() +ADD_DEPENDENCIES(nping DPDK) +endif() + +if(WITH_SECUREC_LIB) +TARGET_LINK_LIBRARIES(nping libnStackAPI.so securec -Wl,-rpath=. -lpthread -lrt -ldl) +else() +TARGET_LINK_LIBRARIES(nping libnStackAPI.so -Wl,-rpath=. -lpthread -lrt -ldl) +endif() diff --git a/stacks/lwip_stack/tools/nping.c b/stacks/lwip_stack/tools/nping.c new file mode 100644 index 0000000..09e604f --- /dev/null +++ b/stacks/lwip_stack/tools/nping.c @@ -0,0 +1,627 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <arpa/inet.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <errno.h> +#include <time.h> +#include <fcntl.h> +#include <memory.h> +#include <strings.h> +#include <limits.h> +#include <getopt.h> +#include "nstack_securec.h" +#include "tool_common.h" + +/*======== for global variables =======*/ + +NSTACK_STATIC input_info g_input_info = { 0 }; +static stat_info g_stat_info = { 0 }; + +static char *g_nping_short_options = "c:r:I:"; + +int g_exit = 0; +void +user_exit (int sig) +{ + g_exit = 1; +} + +NSTACK_STATIC inline double +get_cost_time (struct timespec *pstart, struct timespec *pend) +{ + double sec = (double) (pend->tv_sec - pstart->tv_sec); + double nsec = (double) (pend->tv_nsec - pstart->tv_nsec); + + return (sec * 1000 + (nsec / 1000000)); +} + +NSTACK_STATIC inline double +get_lost_rate (unsigned int lost_count, unsigned int send_count) +{ + if (0 == send_count) + { + return 0; + } + + return ((double) lost_count / send_count); +} + +void +print_stat (stat_info * info, const char *remote_ip) +{ + unsigned int send_count = info->send_seq; + unsigned int recv_count = info->recv_ok; + unsigned int lost_count = send_count - recv_count; + double lost_rate = 100 * get_lost_rate (lost_count, send_count); + double cost_time = get_cost_time (&info->start_time, &info->end_time); + + printf ("\n------ %s ping statistics ------\n", remote_ip); + + printf + ("%u packets transmitted, %u received, %.2f%% packet loss, time %.2fms\n", + send_count, recv_count, lost_rate, cost_time); + + if (0 != recv_count) + { + double min_interval = info->min_interval; + double max_interval = info->max_interval; + double avg_interval = info->all_interval / recv_count; + printf ("rtt min/avg/max = %.3f/%.3f/%.3f ms\n", min_interval, + avg_interval, max_interval); + } +} + +NSTACK_STATIC inline u16 +get_chksum (icmp_head * pmsg) +{ + int len = sizeof (icmp_head); + u32 sum = 0; + u16 *msg_stream = (u16 *) pmsg; + u16 check_sum = 0; + + while (len > 1) + { + sum += *msg_stream; + len -= 2; + msg_stream++; + } + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + check_sum = ~sum; + + return check_sum; +} + +#ifndef MAX_SHORT +#define MAX_SHORT 0xFFFF +#endif + +NSTACK_STATIC inline void +code_icmp_req (icmp_head * pmsg, u32 send_seq, pid_t my_pid) +{ + struct timespec cur_time; + + pmsg->icmp_type = ICMP_ECHO; + pmsg->icmp_code = 0; + pmsg->icmp_cksum = 0; + pmsg->icmp_seq = send_seq % (MAX_SHORT + 1); + pmsg->icmp_id = my_pid; + pmsg->timestamp = 0; + + if (0 != clock_gettime (CLOCK_MONOTONIC, &cur_time)) + { + printf ("Failed to get time, errno = %d\n", errno); + } + + pmsg->icmp_sec = cur_time.tv_sec; + pmsg->icmp_nsec = cur_time.tv_nsec; + + pmsg->icmp_cksum = get_chksum (pmsg); + return; +} + +NSTACK_STATIC int +send_icmp_req (int socket, pid_t my_pid, stat_info * stat, + struct sockaddr_in *remote_addr) +{ + int send_ret; + icmp_head icmp_req; + + stat->send_seq++; + code_icmp_req (&icmp_req, stat->send_seq, my_pid); + + send_ret = sendto (socket, &icmp_req, sizeof (icmp_head), 0, + (struct sockaddr *) remote_addr, + sizeof (struct sockaddr_in)); + + if (send_ret < 0) + { + printf ("send icmp request failed.\n"); + return -1; + } + + return send_ret; +} + +NSTACK_STATIC inline double +cal_interval (struct timespec *psend, struct timespec *precv, + stat_info * stat) +{ + double interval = get_cost_time (psend, precv); + + stat->all_interval += interval; + + if (interval < stat->min_interval) + { + stat->min_interval = interval; + } + + if (interval > stat->max_interval) + { + stat->max_interval = interval; + } + + return interval; +} + +NSTACK_STATIC inline void +print_info_on_reply (long send_sec, long send_usec, u32 send_seq, + stat_info * stat, struct sockaddr_in *dst_addr) +{ + struct timespec send_time; + struct timespec recv_time; + if (0 != clock_gettime (CLOCK_MONOTONIC, &recv_time)) + { + printf ("Failed to get time, errno = %d\n", errno); + } + + send_time.tv_sec = send_sec; + send_time.tv_nsec = send_usec; + + double interval = cal_interval (&send_time, &recv_time, stat); + const char *remote_ip = inet_ntoa (dst_addr->sin_addr); + printf ("%lu bytes from %s: icmp_seq=%u, time=%.3f ms\n", + sizeof (icmp_head), remote_ip, send_seq % (MAX_SHORT + 1), + interval); +} + +NSTACK_STATIC inline void +print_info_on_no_reply (u32 send_seq, const char *remote_ip) +{ + printf ("No data from %s, icmp_seq=%u, Destination Host Unreachable\n", + remote_ip, send_seq); +} + +static inline int +expect_addr (int expect, int addr) +{ + return (expect == addr); +} + +NSTACK_STATIC inline int +parse_icmp_reply (char *buf, unsigned int buf_len, u32 my_pid, u32 send_seq, + stat_info * stat, struct sockaddr_in *dst_addr) +{ + unsigned int ip_head_len; + ip_head *recv_ip_head; + icmp_head *recv_icmp_head; + + // parse all received ip package + while (buf_len > sizeof (ip_head)) + { + recv_ip_head = (ip_head *) buf; + + ip_head_len = recv_ip_head->ihl << 2; + recv_icmp_head = (icmp_head *) (buf + ip_head_len); + buf_len -= htons (recv_ip_head->tot_len); + + if (!expect_addr (dst_addr->sin_addr.s_addr, recv_ip_head->local_ip)) + { + return 0; + } + + if ((recv_icmp_head->icmp_type == ICMP_REPLY) + && (recv_icmp_head->icmp_id == my_pid) + && (recv_icmp_head->icmp_seq == send_seq % (MAX_SHORT + 1))) + { + print_info_on_reply (recv_icmp_head->icmp_sec, + recv_icmp_head->icmp_nsec, send_seq, stat, + dst_addr); + + return 1; + } + + buf += ip_head_len; + } + + return 0; +} + +NSTACK_STATIC inline int +recv_icmp_reply_ok (int socket, int my_pid, u32 send_seq, stat_info * stat, + struct sockaddr_in *dst_addr) +{ +#define MAX_RECV_BUFF_SIZE (200 * sizeof(icmp_head)) + + struct sockaddr_in remote_addr; + unsigned int addr_len = sizeof (remote_addr); + char recv_buf[MAX_RECV_BUFF_SIZE]; + + int recv_ret = recvfrom (socket, recv_buf, MAX_RECV_BUFF_SIZE, 0, + (struct sockaddr *) &remote_addr, &addr_len); + + if (recv_ret < 0) + { + return 0; + } + + if (!parse_icmp_reply + (recv_buf, (unsigned int) recv_ret, my_pid, send_seq, stat, dst_addr)) + { + return 0; + } + + return 1; +} + +// check recv msg in 2 us +/* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50811*/ +NSTACK_STATIC void +recv_icmp_reply (int socket, pid_t my_pid, input_info * input, + stat_info * stat, struct sockaddr_in *dst_addr) +/* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ +{ +#define MAX_SLEEP_TIME (2 * US_TO_NS) +#define MAX_WAIT_TIME (1000 * MS_TO_NS) + + int recv_ok = 0; + int retry = 0; + long sleep_all = 0; + long sleep_time = 0; + + u32 expect_seq = stat->send_seq; + + while (retry < input->retry_count) + { + if (recv_icmp_reply_ok (socket, my_pid, expect_seq, stat, dst_addr)) + { + recv_ok = 1; + stat->recv_ok++; + break; + } + + sleep_all += MAX_SLEEP_TIME; + sys_sleep_ns (0, MAX_SLEEP_TIME); + retry++; + } + + if (!recv_ok) + { + print_info_on_no_reply (expect_seq, input->dst_ip); + } + + if (sleep_all < MAX_WAIT_TIME) + { + sleep_time = MAX_WAIT_TIME - sleep_all; + sys_sleep_ns (0, sleep_time); + } +} + +NSTACK_STATIC inline int +is_digit_nping (char *str) +{ + if (NULL == str || '\0' == str[0]) + { + return 0; + } + + while (*str) + { + if (*str > '9' || *str < '0') + { + return 0; + } + + str++; + } + + return 1; +} + +#define MIN_IP_LEN_NPING 7 //the length of string ip addr x.x.x.x is 7, 4 numbers + 3 dots = 7 +#define MAX_IP_LEN_NPING 15 //the length of string ip addr xxx.xxx.xxx.xxx is 15, 12 numbers + 3 dots = 15 + +NSTACK_STATIC inline int +is_ip_addr_nping (char *param_addr) +{ + int ipseg1; + int ipseg2; + int ipseg3; + int ipseg4; + + if (NULL == param_addr) + { + return 0; + } + + size_t len = strlen (param_addr); + if (len < MIN_IP_LEN_NPING || len > MAX_IP_LEN_NPING) // valid ip MIN_IP_LEN=7, MAX_IP_LEN=15 + { + printf ("Input IP format error.\n"); + return 0; + } + + if (SSCANF_S (param_addr, "%d.%d.%d.%d", &ipseg1, &ipseg2, &ipseg3, &ipseg4) + != 4) + { + return 0; + } + + if ((ipseg1 & 0xffffff00) + || (ipseg2 & 0xffffff00) + || (ipseg3 & 0xffffff00) || (ipseg4 & 0xffffff00)) + { + return 0; + } + + return 1; +} + +NSTACK_STATIC inline bool +check_nping_input_para (input_info * input) +{ + if (input->send_count < 1) + { + return false; + } + + if (input->retry_count < NPING_RETRY_COUNT + || input->retry_count > MAX_NPING_RETRY_COUNT) + { + return false; + } + + if (0 == input->src_ip[0] || 0 == input->dst_ip[0]) + { + return false; + } + + return true; +} + +NSTACK_STATIC inline bool +get_nping_input_para (int argc, char **argv, input_info * input) +{ + int opt = 0; + bool arg_invalid = false; + + if (argc < 2) + { + return false; + } + + if (!is_ip_addr_nping (argv[1])) + { + return false; + } + + /* CID 36687 (#1 of 2): Unchecked return value (CHECKED_RETURN) */ + if (EOK != STRCPY_S (input->dst_ip, sizeof (input->dst_ip), argv[1])) + { + printf ("STRCPY_S failed.\n"); + return false; + } + + while (1) + { + opt = getopt (argc - 1, &argv[1], g_nping_short_options); + if (-1 == opt) + { + break; + } + + switch (opt) + { + // for short options + case 'c': + input->send_count = atoi (optarg); + break; + case 'r': + input->retry_count = atoi (optarg); + break; + case 'I': + /* CID 36687 (#2 of 2): Unchecked return value (CHECKED_RETURN) */ + if (!is_ip_addr_nping (optarg)) + { + return false; + } + if (EOK != STRCPY_S (input->src_ip, sizeof (input->src_ip), optarg)) + { + printf ("STRCPY_S failed.\n"); + return false; + } + break; + default: + arg_invalid = true; + break; + } + + if (arg_invalid) + { + return false; + } + } + + if (!check_nping_input_para (input)) + { + return false; + } + + return true; +} + +void +print_help_nping () +{ + printf + ("usage:nping destination [-c send_count -I src_addr -r retry_count]\n"); + printf ("send count range:1-2147483647\n"); + printf ("retry count range:1000-20000\n"); +} + +NSTACK_STATIC inline void +init_input_info (input_info * input) +{ + if (EOK != MEMSET_S (input, sizeof (input_info), 0, sizeof (input_info))) + { + printf ("MEMSET_S failed.\n"); + return; + } + + input->send_count = 100000; + input->retry_count = NPING_RETRY_COUNT; +} + +NSTACK_STATIC inline void +init_stat_info (stat_info * stat) +{ + stat->max_interval = 0; + stat->min_interval = 0xFFFFFFFF; +} + +#ifndef NSTACK_STATIC_CHECK +int +main (int argc, char *argv[]) +#else +int +nping_main (int argc, char *argv[]) +#endif +{ + struct sockaddr_in local_addr; + struct sockaddr_in remote_addr; + int send_ret; + int ret = -1; + int icmp_sock; + + pid_t my_pid; + + if (EOK != + MEMSET_S (&local_addr, sizeof (local_addr), 0, sizeof (local_addr))) + { + printf ("MEMSET_S failed.\n"); + return 0; + } + local_addr.sin_family = AF_INET; + + init_input_info (&g_input_info); + init_stat_info (&g_stat_info); + + if (!get_nping_input_para (argc, argv, &g_input_info)) + { + print_help_nping (); + return 0; + } + + if ((icmp_sock = socket (AF_INET, CUSTOM_SOCK_TYPE, IPPROTO_ICMP)) < 0) + { + printf ("create socket failed.\n"); + return 0; + } + + local_addr.sin_addr.s_addr = inet_addr (g_input_info.src_ip); + + if (0 != + bind (icmp_sock, (struct sockaddr *) &local_addr, + sizeof (struct sockaddr))) + { + printf ("bind failed, src ip %s\n", g_input_info.src_ip); + close (icmp_sock); + return 0; + } + + int opt = 1; + ret = ioctl (icmp_sock, FIONBIO, &opt); + if (-1 == ret) + { + printf ("fcntl O_NONBLOCK fail\n"); + close (icmp_sock); + return 0; + } + + if (EOK != + MEMSET_S (&remote_addr, sizeof (remote_addr), 0, sizeof (remote_addr))) + { + printf ("MEMSET_S failed.\n"); + close (icmp_sock); + return 0; + } + + remote_addr.sin_family = AF_INET; + remote_addr.sin_addr.s_addr = inet_addr (g_input_info.dst_ip); + + my_pid = getpid (); + printf ("nping %s %lu bytes of data, pid:%d.\n", g_input_info.dst_ip, + sizeof (icmp_head), my_pid); + + signal (SIGINT, user_exit); + + int loop_count = 0; + if (0 != clock_gettime (CLOCK_MONOTONIC, &g_stat_info.start_time)) + { + printf ("Failed to get time, errno = %d\n", errno); + } + +/* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50811*/ + i32 send_count = g_input_info.send_count; +/* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ + + while (!g_exit && (loop_count < send_count)) + { + send_ret = + send_icmp_req (icmp_sock, my_pid, &g_stat_info, &remote_addr); + if (send_ret < 0) + { + break; + } + + recv_icmp_reply (icmp_sock, my_pid, &g_input_info, &g_stat_info, + &remote_addr); + + loop_count++; + } + + close (icmp_sock); + + if (0 != clock_gettime (CLOCK_MONOTONIC, &g_stat_info.end_time)) + { + printf ("Failed to get time, errno = %d\n", errno); + } + + print_stat (&g_stat_info, g_input_info.dst_ip); + + return 0; +} diff --git a/stacks/lwip_stack/tools/ntcpdump.c b/stacks/lwip_stack/tools/ntcpdump.c new file mode 100644 index 0000000..31a96bc --- /dev/null +++ b/stacks/lwip_stack/tools/ntcpdump.c @@ -0,0 +1,1368 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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 <arpa/inet.h> +#include <unistd.h> +#include <signal.h> +#include <time.h> +#include <malloc.h> +#include <stdio.h> +#include <getopt.h> +#include <unistd.h> +#include "types.h" +#include "nsfw_init.h" +#include "nsfw_mem_api.h" +#include "nsfw_fd_timer_api.h" +#include "nsfw_maintain_api.h" +#include "nstack_securec.h" + +#include "tool_common.h" + +NSTACK_STATIC struct option g_dump_long_options[] = { + {"host", 1, NULL, OPT_ARG_HOST}, + {"lhost", 1, NULL, OPT_ARG_LOCAL_HOST}, + {"rhost", 1, NULL, OPT_ARG_REMOTE_HOST}, + {"port", 1, NULL, OPT_ARG_PORT}, + {"lport", 1, NULL, OPT_ARG_LOCAL_PORT}, + {"rport", 1, NULL, OPT_ARG_REMOTE_PORT}, + {"mac", 1, NULL, OPT_ARG_MAC}, + {"lmac", 1, NULL, OPT_ARG_LOCAL_MAC}, + {"rmac", 1, NULL, OPT_ARG_REMOTE_MAC}, + {0, 0, 0, 0} +}; + +static char *g_dump_short_options = "c:s:w:y:G:P:T:"; + +NSTACK_STATIC FILE *g_dump_fp = NULL; +static u32 g_dumped_packet = 0; +NSTACK_STATIC u32 g_captured_packet = 0; +static u32 g_filtered_packet = 0; + +NSTACK_STATIC bool g_dump_exit = 0; + +static dump_timer_info g_dump_hbt_timer; +NSTACK_STATIC dump_condition g_dump_condition; +static nsfw_mem_name g_dump_mem_ring_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, DUMP_SHMEM_RIGN_NAME }; +static nsfw_mem_name g_dump_mem_pool_info = + { NSFW_SHMEM, NSFW_PROC_MAIN, DUMP_SHMEM_POOL_NAME }; + +void +dump_exit () +{ + g_dump_exit = 1; +} + +void +print_help_ntcpdump () +{ + printf ("usage:ntcpdump \n\ + -c count \n\ + -s len \n\ + -w file \n\ + -y l2_protocol \n\ + -T l3_protocol \n\ + -G dump_seconds \n\ + -P in/out/inout \n\ + --host/rhost/lhost ip_addr \n\ + --port/rport/lport port \n\ + --mac/rmac/lmac mac_addr\n"); +} + +bool +is_digit_ntcpdump (char *str, size_t src_len) +{ + size_t count = 0; + + if (NULL == str || 0 == *str) + { + return FALSE; + } + + while (*str) + { + if (*str > '9' || *str < '0') + { + return false; + } + + str++; + count++; + } + + if (count > src_len) + { + return false; + } + + return true; +} + +NSTACK_STATIC inline bool +is_ip_addr (const char *addr, ip_addr_bits * addr_info) +{ + u32 ip1; + u32 ip2; + u32 ip3; + u32 ip4; + + if (SSCANF_S (addr, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4) != 4) + { + return false; + } + + if ((ip1 & 0xffffff00) || (ip2 & 0xffffff00) || (ip3 & 0xffffff00) + || (ip4 & 0xffffff00)) + { + return false; + } + + addr_info->addr_bits1 = ip1; + addr_info->addr_bits2 = ip2; + addr_info->addr_bits3 = ip3; + addr_info->addr_bits4 = ip4; + + return true; +} + +NSTACK_STATIC inline bool +get_ip_addr (const char *addr, u32 * ip_addr) +{ + ip_addr_bits addr_info; + if (!is_ip_addr (addr, &addr_info)) + { + return false; + } + + *ip_addr = ((addr_info.addr_bits1 & 0xFF) + | (addr_info.addr_bits2 & 0xFF) << 8 + | (addr_info.addr_bits3 & 0xFF) << 16 + | (addr_info.addr_bits4 & 0xFF) << 24); + + return true; +} + +NSTACK_STATIC inline bool +get_dump_port (const char *pport, u16 * port) +{ + int user_port; + + if (!is_digit_ntcpdump ((char *) pport, MAX_PORT_STR_LEN)) + { + return false; + } + + user_port = atoi (pport); + if (user_port < 1024 || user_port > 65535) + { + return false; + } + + *port = (unsigned short) user_port; + return true; +} + +NSTACK_STATIC inline bool +get_dump_len (char *plen, u32 * limit_len) +{ + if (!is_digit_ntcpdump (plen, MAX_INTEGER_STR_LEN)) + { + return false; + } + + *limit_len = atoi (plen); + return true; +} + +NSTACK_STATIC inline bool +get_mac_addr (const char *opt_value, char *mac_addr) +{ + /* avoid coredump when opt_value is NULL */ + if (NULL == opt_value) + { + return false; + } + + size_t org_len = strlen (opt_value); + if (org_len != MAC_ADDR_STR_LEN) + { + return false; + } + + u32 tmp_mac[MAC_ADDR_LEN]; + + if (6 != SSCANF_S (opt_value, "%x:%x:%x:%x:%x:%x", + &tmp_mac[0], + &tmp_mac[1], + &tmp_mac[2], &tmp_mac[3], &tmp_mac[4], &tmp_mac[5])) + { + return false; + } + + int i = 0; + for (; i < MAC_ADDR_LEN; i++) + { + if (tmp_mac[i] > 0xFF) + { + // 01:02:03:04:5:1FF + return false; + } + + mac_addr[i] = tmp_mac[i]; + } + + return true; +} + +NSTACK_STATIC inline bool +check_file_name (const char *file_name) +{ + if (0 == access (file_name, F_OK)) + { + printf ("dump file exist, file name=%s.\n", file_name); + return false; + } + return true; +} + +NSTACK_STATIC inline u16 +get_para_direction (const char *para) +{ + if (0 == strcasecmp (para, "out")) + { + return DUMP_SEND; + } + + if (0 == strcasecmp (para, "in")) + { + return DUMP_RECV; + } + + if (0 == strcasecmp (para, "inout")) + { + return DUMP_SEND_RECV; + } + + return INVALID_DIRECTION; +} + +NSTACK_STATIC inline u16 +get_para_l2_protocol (const char *para) +{ + if (0 == strcasecmp (para, "arp")) + { + return PROTOCOL_ARP; + } + + if (0 == strcasecmp (para, "rarp")) + { + return PROTOCOL_RARP; + } + + if (0 == strcasecmp (para, "ip")) + { + return PROTOCOL_IP; + } + + if (0 == strcasecmp (para, "oam")) + { + return PROTOCOL_OAM_LACP; + } + + if (0 == strcasecmp (para, "lacp")) + { + return PROTOCOL_OAM_LACP; + } + + return INVALID_L2_PROTOCOL; +} + +NSTACK_STATIC inline u16 +get_para_l3_protocol (const char *para) +{ + if (0 == strcasecmp (para, "tcp")) + { + return PROTOCOL_TCP; + } + + if (0 == strcasecmp (para, "udp")) + { + return PROTOCOL_UDP; + } + + if (0 == strcasecmp (para, "icmp")) + { + return PROTOCOL_ICMP; + } + + return INVALID_L3_PROTOCOL; +} + +NSTACK_STATIC bool +parse_long_options (int opt, const char *long_opt_arg, int optindex, + dump_condition * filter_info) +{ + switch (opt) + { + case OPT_ARG_HOST: + if (!get_ip_addr (long_opt_arg, &filter_info->ip_addr)) + { + printf ("invalid ip addr, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->ip_set_flag |= COND_OR_SET; + break; + case OPT_ARG_LOCAL_HOST: + if (!get_ip_addr (long_opt_arg, &filter_info->local_ip)) + { + printf ("invalid ip addr, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->ip_set_flag |= COND_LOCAL_SET; + break; + case OPT_ARG_REMOTE_HOST: + if (!get_ip_addr (long_opt_arg, &filter_info->remote_ip)) + { + printf ("invalid ip addr, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->ip_set_flag |= COND_REMOTE_SET; + break; + case OPT_ARG_PORT: + if (!get_dump_port (long_opt_arg, &filter_info->port)) + { + printf ("invalid port, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->port_set_flag |= COND_OR_SET; + break; + case OPT_ARG_LOCAL_PORT: + if (!get_dump_port (long_opt_arg, &filter_info->local_port)) + { + printf ("invalid port, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->port_set_flag |= COND_LOCAL_SET; + break; + case OPT_ARG_REMOTE_PORT: + if (!get_dump_port (long_opt_arg, &filter_info->remote_port)) + { + printf ("invalid port, optindex=%d, port=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->port_set_flag |= COND_REMOTE_SET; + break; + case OPT_ARG_MAC: + if (!get_mac_addr (long_opt_arg, filter_info->mac_addr)) + { + printf ("invalid mac addr, optindex=%d, mac=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->mac_set_flag |= COND_OR_SET; + break; + case OPT_ARG_LOCAL_MAC: + if (!get_mac_addr (long_opt_arg, filter_info->local_mac)) + { + printf ("invalid mac addr, optindex=%d, mac=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->mac_set_flag |= COND_LOCAL_SET; + break; + case OPT_ARG_REMOTE_MAC: + if (!get_mac_addr (long_opt_arg, filter_info->remote_mac)) + { + printf ("invalid mac addr, optindex=%d, mac=%s.\n", optindex, + long_opt_arg); + return false; + } + filter_info->mac_set_flag |= COND_REMOTE_SET; + break; + default: + printf ("unknow arg, optindex=%d, arg=%s.\n", optindex, long_opt_arg); + return false; + } + + return true; +} + +NSTACK_STATIC inline bool +condition_valid (dump_condition * condition) +{ + // check direction + if (INVALID_DIRECTION == condition->direction) + { + printf ("direction invalid.\n"); + return false; + } + + // check l2 protocol + if (INVALID_L2_PROTOCOL == condition->l2_protocol) + { + printf ("L2 protocol invalid.\n"); + return false; + } + + // check l3 protocol + if (INVALID_L3_PROTOCOL == condition->l3_protocol) + { + printf ("L3 protocol invalid.\n"); + return false; + } + + // check ip + if (condition->ip_set_flag > 0x4) + { + printf ("IP options invalid.\n"); + return false; + } + + // check port + if (condition->port_set_flag > 0x4) + { + printf ("Port options invalid.\n"); + return false; + } + + // check mac + if (condition->mac_set_flag > 0x4) + { + printf ("MAC options invalid.\n"); + return false; + } + + if (condition->dump_time > MAX_DUMP_TIME + || condition->dump_time < MIN_DUMP_TIME) + { + printf ("dump time invalid.\n"); + return false; + } + + return true; +} + +NSTACK_STATIC inline bool +get_dump_condition (int argc, char **argv, dump_condition * filter_info) +{ + int opt = 0; + int opt_index = 0; + bool arg_invalid = false; + filter_info->has_condition = 0; + + if (argc < 2) + { + // dump all package + return true; + } + + while (1) + { + opt = + getopt_long (argc, argv, g_dump_short_options, g_dump_long_options, + &opt_index); + if (-1 == opt) + { + break; + } + + switch (opt) + { + // for short options + case 'c': + filter_info->dump_count = atoi (optarg); + break; + case 's': + if (!get_dump_len (optarg, &filter_info->limit_len)) + { + printf ("length invalid, optindex=%d, arg=%s.\n", opt_index, + optarg); + arg_invalid = true; + } + break; + case 'w': + if (!check_file_name (optarg)) + { + printf ("invalid file name, optindex=%d, arg=%s.\n", opt_index, + optarg); + arg_invalid = true; + } + else + { + filter_info->dump_file_name = optarg; + } + break; + case 'y': + filter_info->l2_protocol = get_para_l2_protocol (optarg); + break; + case 'G': + filter_info->dump_time = atoi (optarg); + break; + case 'P': + filter_info->direction = get_para_direction (optarg); + break; + case 'T': + filter_info->l3_protocol = get_para_l3_protocol (optarg); + break; + case '?': + arg_invalid = true; + break; + // for long options + default: + if (!parse_long_options (opt, optarg, opt_index, filter_info)) + { + arg_invalid = true; + } + break; + } + + if (arg_invalid) + { + print_help_ntcpdump (); + return false; + } + + filter_info->has_condition = 1; + } + + if (!condition_valid (filter_info)) + { + filter_info->has_condition = 0; + return false; + } + + return true; +} + +NSTACK_STATIC inline void +open_file () +{ + if (NULL == g_dump_condition.dump_file_name) + { + return; + } + + g_dump_fp = fopen (g_dump_condition.dump_file_name, "w+"); + if (NULL == g_dump_fp) + { + printf ("open file %s failed\n", g_dump_condition.dump_file_name); + } +} + +NSTACK_STATIC inline void +close_file () +{ + if (NULL != g_dump_fp) + { + fclose (g_dump_fp); + g_dump_fp = NULL; + } +} + +NSTACK_STATIC inline void +write_file_head (FILE * fp) +{ + dump_file_head file_head; + file_head.magic = 0xA1B2C3D4; + file_head.major_ver = 2; // 0x0200; + file_head.minor_ver = 4; // 0x0400; + file_head.area = 0; + file_head.time_stamp = 0; + file_head.max_pack_size = 0x0000FFFF; // 0xFFFF0000; + file_head.link_type = 1; //0x01000000; + + if (fwrite (&file_head, sizeof (dump_file_head), 1, fp) != 1) + { + return; + } + + fflush (fp); +} + +NSTACK_STATIC inline void +write_packet (parse_msg_info * pmsg, FILE * fp) +{ + packet_head pack_head; + dump_msg_info *org_msg = (dump_msg_info *) pmsg->org_msg; + pack_head.sec = org_msg->dump_sec; + pack_head.usec = org_msg->dump_usec; + pack_head.save_len = + (u32) nstack_min (org_msg->len, g_dump_condition.limit_len); + pack_head.org_len = org_msg->len; + + if (fwrite (&pack_head, sizeof (packet_head), 1, fp) != 1) + { + // log error + return; + } + + if (fwrite (org_msg->buf, pack_head.save_len, 1, fp) != 1) + { + // log error + return; + } + + fflush (fp); + return; +} + +#define EMPTY(x) (0 == (x)) +#define EQUAL(x, y) ((x) == (y)) + +#define STR_EMPTY(str) (0 == str[0]) +#define STR_EQUAL(str1, str2, len) (0 == memcmp(str1, str2, len)) + +#define MATCH(cond, info, field) \ + (EQUAL(cond->field, info->field)) + +#define MATCH_MORE(cond, field, info, field1, field2) \ + (EQUAL(cond->field, info->field1) || EQUAL(cond->field, info->field2)) + +#define MATCH_STR(cond, info, field, len) \ + (STR_EQUAL(cond->field, info->field, len)) + +#define MATCH_STR_MORE(cond, field, info, field1, field2, len) \ + (STR_EQUAL(cond->field, info->field1, len) || STR_EQUAL(cond->field, info->field2, len)) + +NSTACK_STATIC inline bool +ip_match (dump_condition * condition, parse_msg_info * msg_info) +{ + bool ret = false; + switch (condition->ip_set_flag) + { + case COND_NOT_SET: + ret = true; + break; + case COND_LOCAL_SET: + if (MATCH (condition, msg_info, local_ip)) + { + ret = true; + } + break; + case COND_REMOTE_SET: + if (MATCH (condition, msg_info, remote_ip)) + { + ret = true; + } + break; + case COND_AND_SET: + if (MATCH_MORE (condition, local_ip, msg_info, local_ip, remote_ip) + && MATCH_MORE (condition, remote_ip, msg_info, local_ip, remote_ip)) + { + ret = true; + } + break; + case COND_OR_SET: + if (MATCH_MORE (condition, ip_addr, msg_info, local_ip, remote_ip)) + { + ret = true; + } + break; + default: + break; + } + + return ret; +} + +NSTACK_STATIC inline bool +port_match (dump_condition * condition, parse_msg_info * msg_info) +{ + bool ret = false; + switch (condition->port_set_flag) + { + case COND_NOT_SET: + ret = true; + break; + case COND_LOCAL_SET: + if (MATCH (condition, msg_info, local_port)) + { + ret = true; + } + break; + case COND_REMOTE_SET: + if (MATCH (condition, msg_info, remote_port)) + { + ret = true; + } + break; + case COND_AND_SET: + if (MATCH (condition, msg_info, local_port) + && MATCH (condition, msg_info, remote_port)) + { + ret = true; + } + break; + case COND_OR_SET: + if (MATCH_MORE (condition, port, msg_info, local_port, remote_port)) + { + ret = true; + } + break; + default: + break; + } + + return ret; +} + +NSTACK_STATIC inline bool +mac_match (dump_condition * condition, parse_msg_info * msg_info) +{ + bool ret = false; + switch (condition->mac_set_flag) + { + case COND_NOT_SET: + ret = true; + break; + case COND_LOCAL_SET: + if (MATCH_STR (condition, msg_info, local_mac, MAC_ADDR_LEN)) + { + ret = true; + } + break; + case COND_REMOTE_SET: + if (MATCH_STR (condition, msg_info, remote_mac, MAC_ADDR_LEN)) + { + ret = true; + } + break; + case COND_AND_SET: + if ((MATCH_STR_MORE + (condition, local_mac, msg_info, local_mac, remote_mac, + MAC_ADDR_LEN) + && MATCH_STR_MORE (condition, remote_mac, msg_info, local_mac, + remote_mac, MAC_ADDR_LEN))) + { + ret = true; + } + break; + case COND_OR_SET: + if (MATCH_STR_MORE + (condition, mac_addr, msg_info, local_mac, remote_mac, + MAC_ADDR_LEN)) + { + ret = true; + } + break; + default: + break; + } + + return ret; +} + +NSTACK_STATIC inline bool +filter_by_condition (dump_condition * condition, parse_msg_info * msg_info) +{ + dump_msg_info *org_msg = (dump_msg_info *) msg_info->org_msg; + if (0 == condition->has_condition) + { + return false; + } + + // direction + if (!(condition->direction & org_msg->direction)) + { + return true; + } + + // l2_protocol + if ((0 != condition->l2_protocol) + && !MATCH (condition, msg_info, l2_protocol)) + { + return true; + } + + // l3_protocol + if ((0 != condition->l3_protocol) + && !MATCH (condition, msg_info, l3_protocol)) + { + return true; + } + + // ip + if (!ip_match (condition, msg_info)) + { + return true; + } + + // port + if (!port_match (condition, msg_info)) + { + return true; + } + + // mac + if (!mac_match (condition, msg_info)) + { + return true; + } + + return false; +} + +NSTACK_STATIC inline char * +get_l2_protocol_desc (u16 l2_protocol) +{ + switch (l2_protocol) + { + case PROTOCOL_IP: + return "IP"; + case PROTOCOL_ARP: + return "ARP"; + case PROTOCOL_RARP: + return "RARP"; + case PROTOCOL_OAM_LACP: + return "OAM/LACP"; + default: + return "unknown"; + } +} + +NSTACK_STATIC inline char * +get_l3_protocol_desc (u16 l3_protocol) +{ + switch (l3_protocol) + { + case PROTOCOL_ICMP: + return "ICMP"; + case PROTOCOL_TCP: + return "TCP"; + case PROTOCOL_UDP: + return "UDP"; + default: + return "unknown"; + } +} + +NSTACK_STATIC inline void +get_ip_str (char *pip_addr, u32 ip_addr_len, u32 ip) +{ + int retVal; + retVal = SPRINTF_S (pip_addr, ip_addr_len, "%d.%d.%d.%d", + ip & 0x000000FF, + (ip & 0x0000FF00) >> 8, + (ip & 0x00FF0000) >> 16, (ip & 0xFF000000) >> 24); + if (-1 == retVal) + { + printf ("get_ip_str:SPRINTF_S failed %d.\n", retVal); + } +} + +NSTACK_STATIC inline void +print_packet (parse_msg_info * msg_info, u32 seq) +{ + char str_local_ip[IP_ADDR_LEN]; + char str_remote_ip[IP_ADDR_LEN]; + get_ip_str (str_local_ip, sizeof (str_local_ip), msg_info->local_ip); + get_ip_str (str_remote_ip, sizeof (str_remote_ip), msg_info->remote_ip); + + dump_msg_info *org_msg = (dump_msg_info *) msg_info->org_msg; + + printf ("%-6d %-6d:%6d %-8s %-8s %-16s %-16s %-10d %-10d %-8d\n", + seq, + org_msg->dump_sec, org_msg->dump_usec, + get_l2_protocol_desc (msg_info->l2_protocol), + get_l3_protocol_desc (msg_info->l3_protocol), + str_local_ip, + str_remote_ip, + msg_info->local_port, msg_info->remote_port, org_msg->len); +} + +void +print_head () +{ + if (NULL != g_dump_fp) + { + write_file_head (g_dump_fp); + } + else + { + printf ("ntcpdump start listening:\n"); + printf ("%-6s %-18s %-8s %-8s %-16s %-16s %-10s %-10s %-8s\n", + "Frame", "sec:usec", "L2", "L3", "Src IP", "Dest IP", + "Src Port", "Dest Port", "Length"); + } +} + +void +register_dump_signal () +{ + signal (SIGINT, dump_exit); +} + +NSTACK_STATIC inline void +init_parse_msg_info (parse_msg_info * info) +{ + int retVal = + MEMSET_S (info, sizeof (parse_msg_info), 0, sizeof (parse_msg_info)); + if (EOK != retVal) + { + printf ("MEMSET_S failed.\n"); + } +} + +NSTACK_STATIC inline void +parse_msg (dump_msg_info * msg, parse_msg_info * info) +{ + init_parse_msg_info (info); + + info->org_msg = msg; + + char *pmsg = msg->buf; + u32 len = msg->len; + /* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50886 */ + if (len < MAC_ADDR_LEN + MAC_ADDR_LEN + sizeof (u16)) + { + return; + } + /* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ + + // get mac addr + if (EOK != + MEMCPY_S (info->remote_mac, sizeof (info->remote_mac), pmsg, + MAC_ADDR_LEN)) + { + return; + } + + pmsg += MAC_ADDR_LEN; + len -= MAC_ADDR_LEN; + + if (EOK != + MEMCPY_S (info->local_mac, sizeof (info->local_mac), pmsg, + MAC_ADDR_LEN)) + { + return; + } + + pmsg += MAC_ADDR_LEN; + len -= MAC_ADDR_LEN; + + info->l2_protocol = htons (*(u16 *) pmsg); + pmsg += sizeof (u16); + len -= sizeof (u16); + + if (PROTOCOL_IP != info->l2_protocol) + { + return; + } + + ip_head *p_ip_head = (ip_head *) pmsg; + if (len < p_ip_head->ihl) + { + return; + } + + info->local_ip = p_ip_head->local_ip; + info->remote_ip = p_ip_head->remote_ip; + info->l3_protocol = p_ip_head->protocol; + + pmsg += p_ip_head->ihl * sizeof (u32); + + if (PROTOCOL_TCP == info->l3_protocol) + { + tcp_head *p_tcp_head = (tcp_head *) pmsg; + info->local_port = htons (p_tcp_head->src_port); + info->remote_port = htons (p_tcp_head->dst_port); + return; + } + + if (PROTOCOL_UDP == info->l3_protocol) + { + udp_head *p_udp_head = (udp_head *) pmsg; + info->local_port = htons (p_udp_head->src_port); + info->remote_port = htons (p_udp_head->dst_port); + return; + } + + return; +} + +NSTACK_STATIC inline bool +time_expired (struct timespec * start_time, u32 work_sec) +{ +#define TIME_EXPIRE_CHECK_COUNT 1000 + + static u32 loop_count = 0; + loop_count++; + + if (0 != loop_count % TIME_EXPIRE_CHECK_COUNT) + { + return false; + } + + struct timespec cur_time; + GET_CUR_TIME (&cur_time); + + if (cur_time.tv_sec - start_time->tv_sec > work_sec) + { + return true; + } + + return false; +} + +NSTACK_STATIC void +dump_packet (parse_msg_info * msg) +{ + g_dumped_packet++; + if (!g_dump_fp) + { + print_packet (msg, g_dumped_packet); + return; + } + + write_packet (msg, g_dump_fp); +} + +NSTACK_STATIC void +dump_msg (mring_handle dump_ring, mring_handle dump_pool, + dump_condition * condition, struct timespec *start_time) +{ + u32 dump_count = 0; + open_file (); + + print_head (); + + void *msg = NULL; + while (!g_dump_exit + && (dump_count < condition->dump_count) + && !time_expired (start_time, condition->dump_time)) + { + if (nsfw_mem_ring_dequeue (dump_ring, &msg) <= 0) + { + sys_sleep_ns (0, 10000); + continue; + } + + if (NULL == msg) + { + continue; + } + + parse_msg_info msg_info; + parse_msg (msg, &msg_info); + + g_captured_packet++; + if (!condition->has_condition) + { + dump_packet (&msg_info); + dump_count++; + nsfw_mem_ring_enqueue (dump_pool, msg); + continue; + } + + if (filter_by_condition (condition, &msg_info)) + { + g_filtered_packet++; + nsfw_mem_ring_enqueue (dump_pool, msg); + continue; + } + + dump_packet (&msg_info); + dump_count++; + nsfw_mem_ring_enqueue (dump_pool, msg); + } + + close_file (); +} + +mring_handle +dump_get_mem_ring () +{ + return nsfw_mem_ring_lookup (&g_dump_mem_ring_info); +} + +mring_handle +dump_get_mem_pool () +{ + return nsfw_mem_sp_lookup (&g_dump_mem_pool_info); +} + +NSTACK_STATIC void +dump_clear_mem (mring_handle ring, mring_handle pool) +{ + void *msg = NULL; + while (nsfw_mem_ring_dequeue (ring, &msg) > 0) + { + nsfw_mem_ring_enqueue (pool, msg); + sys_sleep_ns (0, 1000); + } +} + +/* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50859*/ +i16 +dump_send_req (u16 op_type, i16 task_id, u32 task_keep_time) +/* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ +{ + nsfw_mgr_msg *req = + (nsfw_mgr_msg *) nsfw_mgr_msg_alloc (MGR_MSG_TOOL_TCPDUMP_REQ, + NSFW_PROC_MAIN); + if (NULL == req) + { + printf ("all message for getting instance id failed.\n"); + return -1; + } + + nsfw_tool_dump_msg *req_body = GET_USER_MSG (nsfw_tool_dump_msg, req); + req_body->op_type = op_type; + req_body->task_id = task_id; + req_body->task_keep_time = task_keep_time; + + nsfw_mgr_msg *rsp = nsfw_mgr_null_rspmsg_alloc (); + if (NULL == rsp) + { + printf ("alloc rsp message for getting memory failed.\n"); + nsfw_mgr_msg_free (req); + return -1; + } + + if (!nsfw_mgr_send_req_wait_rsp (req, rsp)) + { + printf ("request memory can not get response.\n"); + nsfw_mgr_msg_free (req); + nsfw_mgr_msg_free (rsp); + return -1; + } + + if (rsp->src_proc_type != NSFW_PROC_MAIN + || rsp->dst_proc_type != NSFW_PROC_TOOLS) + { + printf + ("dump get wrong response, src or dst proc type error,src proc type=%u, dst proc type=%u.\n", + rsp->src_proc_type, rsp->dst_proc_type); + nsfw_mgr_msg_free (req); + nsfw_mgr_msg_free (rsp); + return -1; + } + + if (rsp->msg_type != MGR_MSG_TOOL_TCPDUMP_RSP) + { + printf ("dump get wrong response, msg type error, msg type=%d.\n", + rsp->msg_type); + nsfw_mgr_msg_free (req); + nsfw_mgr_msg_free (rsp); + return -1; + } + + nsfw_tool_dump_msg *rsp_body = GET_USER_MSG (nsfw_tool_dump_msg, rsp); + +/* BEGIN: Added for PN:CODEDEX by l00351127, 2017/11/14 CID:50859*/ + i16 new_task_id = rsp_body->task_id; +/* END: Added for PN:CODEDEX by l00351127, 2017/11/14 */ + + nsfw_mgr_msg_free (req); + nsfw_mgr_msg_free (rsp); + + return new_task_id; +} + +i16 +start_dump_task (u32 task_keep_time) +{ + return dump_send_req (START_DUMP_REQ, -1, task_keep_time); +} + +i16 +stop_dump_task (i16 task_id) +{ + return dump_send_req (STOP_DUMP_REQ, task_id, 0); +} + +NSTACK_STATIC void +init_dump_condition (dump_condition * condition) +{ + if (EOK != + MEMSET_S (condition, sizeof (dump_condition), 0, + sizeof (dump_condition))) + { + printf ("MEMSET_S failed.\n"); + } + condition->limit_len = DUMP_MSG_SIZE; + condition->dump_time = DEFAULT_DUMP_TIME; + condition->direction = 3; + condition->dump_count = DEFAULT_DUMP_COUNT; +} + +NSTACK_STATIC inline bool +send_hbt_req (u32 seq, i16 task_id) +{ + nsfw_mgr_msg *req = + (nsfw_mgr_msg *) nsfw_mgr_msg_alloc (MGR_MSG_TOOL_HEART_BEAT, + NSFW_PROC_MAIN); + if (NULL == req) + { + printf ("all message for getting instance id failed.\n"); + return false; + } + + nsfw_tool_hbt *req_body = GET_USER_MSG (nsfw_tool_hbt, req); + req_body->seq = seq; + req_body->task_id = task_id; + + if (!nsfw_mgr_send_msg (req)) + { + printf ("request memory can not get response.\n"); + } + + nsfw_mgr_msg_free (req); + + return true; +} + +NSTACK_STATIC bool +on_send_hbt_req (u32 timer_type, void *data) +{ + dump_timer_info *ptimer_info = (dump_timer_info *) data; + // send heartbeat + + send_hbt_req (ptimer_info->seq, ptimer_info->task_id); + ptimer_info->seq++; + + ptimer_info->ptimer = + nsfw_timer_reg_timer (DUMP_HBT_TIMER, ptimer_info, on_send_hbt_req, + *(struct timespec *) (ptimer_info->interval)); + return true; +} + +NSTACK_STATIC bool +start_dump_hbt (dump_timer_info * ptimer_info, i16 task_id) +{ + struct timespec *time_interval = + (struct timespec *) malloc (sizeof (struct timespec)); + if (NULL == time_interval) + { + return false; + } + + time_interval->tv_sec = DUMP_HBT_INTERVAL; + time_interval->tv_nsec = 0; + + ptimer_info->interval = time_interval; + ptimer_info->seq = 1; + ptimer_info->task_id = task_id; + + ptimer_info->ptimer = + nsfw_timer_reg_timer (DUMP_HBT_TIMER, ptimer_info, on_send_hbt_req, + *time_interval); + + return true; +} + +NSTACK_STATIC bool +stop_dump_hbt (dump_timer_info * ptimer_info) +{ + free (ptimer_info->interval); + /* fix "SET_NULL_AFTER_FREE" type codedex issue */ + ptimer_info->interval = NULL; + nsfw_timer_rmv_timer (ptimer_info->ptimer); + return true; +} + +#ifndef NSTACK_STATIC_CHECK +int +main (int argc, char *argv[]) +#else +int +ntcpdump_main (int argc, char *argv[]) +#endif +{ + register_dump_signal (); + + init_dump_condition (&g_dump_condition); + if (!get_dump_condition (argc, argv, &g_dump_condition)) + { + printf ("dump exit because of input invalid.\n"); + return INPUT_INVALID; + } + + printf ("parse filter condition ok.\n"); + + fw_poc_type proc_type = NSFW_PROC_TOOLS; + nsfw_mem_para stinfo = { 0 }; + stinfo.iargsnum = 0; + stinfo.pargs = NULL; + stinfo.enflag = proc_type; + nstack_framework_setModuleParam (NSFW_MEM_MGR_MODULE, &stinfo); + nstack_framework_setModuleParam (NSFW_MGR_COM_MODULE, + (void *) ((u64) proc_type)); + nstack_framework_setModuleParam (NSFW_TIMER_MODULE, + (void *) ((u64) proc_type)); + + if (0 != nstack_framework_init ()) + { + printf ("dump init failed.\n"); + return FRAMEWORK_INIT_FAILED; + } + + mring_handle dump_mem_pool = dump_get_mem_pool (); + if (NULL == dump_mem_pool) + { + printf ("dump init mem pool failed.\n"); + return MEMPOOL_INIT_FAILED; + } + + mring_handle dump_mem_ring = dump_get_mem_ring (); + if (NULL == dump_mem_ring) + { + printf ("dump init mem ring failed.\n"); + return MEMRING_INIT_FAILED; + } + + // initialize queue first + dump_clear_mem (dump_mem_ring, dump_mem_pool); + + i16 task_id = start_dump_task (g_dump_condition.dump_time); + if (task_id < 0 || task_id > MAX_DUMP_TASK) + { + printf ("start dump task failed.\n"); + return START_TASK_FAILED; + } + + if (!start_dump_hbt (&g_dump_hbt_timer, task_id)) + { + printf ("start dump heart beat timer failed.\n"); + return START_TIMER_FAILED; + } + + struct timespec dump_start_time; + GET_CUR_TIME (&dump_start_time); + dump_msg (dump_mem_ring, dump_mem_pool, &g_dump_condition, + &dump_start_time); + + i16 new_task_id = stop_dump_task (task_id); + if (new_task_id != task_id) + { + printf ("stop dump task failed.\n"); + } + /* modify deadcode type codedex issue */ + (void) stop_dump_hbt (&g_dump_hbt_timer); + + printf ("dump complete.\n"); + printf ("captured packets=%u.\n", g_captured_packet); + printf ("dumped packets=%u.\n", g_dumped_packet); + printf ("filtered packets=%u.\n", g_filtered_packet); + + return 0; +} diff --git a/stacks/lwip_stack/tools/tool_common.h b/stacks/lwip_stack/tools/tool_common.h new file mode 100644 index 0000000..6d3526b --- /dev/null +++ b/stacks/lwip_stack/tools/tool_common.h @@ -0,0 +1,243 @@ +/* +* +* Copyright (c) 2018 Huawei Technologies Co.,Ltd. +* 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. +*/ + +#ifndef _TOOL_COMMON_H_ +#define _TOOL_COMMON_H_ + +#include <time.h> +#include "types.h" + +#ifndef NSTACK_STATIC +#ifndef NSTACK_STATIC_CHECK +#define NSTACK_STATIC static +#else +#define NSTACK_STATIC +#endif +#endif + +#ifndef IP_ADDR_LEN +#define IP_ADDR_LEN 16 +#endif + +#ifndef MAC_ADDR_LEN +#define MAC_ADDR_LEN 6 +#endif + +#ifndef MAC_ADDR_STR_LEN +#define MAC_ADDR_STR_LEN 17 +#endif + +#define ICMP_ECHO 8 +#define ICMP_REPLY 0 +#define MS_TO_NS 1000000 +#define US_TO_NS 1000 +#define NPING_RETRY_COUNT 1000 +#define MAX_NPING_RETRY_COUNT 20000 + +#define MAX_PORT_STR_LEN 5 +#define MAX_IP_STR_LEN 15 +#define MAX_INTEGER_STR_LEN 10 + +#define DUMP_HBT_TIMER 1 + +#define INVALID_DIRECTION 0xFFFF +#define DEFAULT_DUMP_COUNT 1000 + +#ifndef CUSTOM_SOCK_TYPE +#define CUSTOM_SOCK_TYPE 0xF001 +#endif + +enum DUMP_ERR_CODE +{ + RET_OK = 0, + INPUT_INVALID = 1, + FRAMEWORK_INIT_FAILED = 2, + MEMPOOL_INIT_FAILED = 3, + MEMRING_INIT_FAILED = 4, + START_TASK_FAILED = 5, + START_TIMER_FAILED = 6, + UNKNOW_ERR +}; + +enum COND_LOCAL_REMOTE_SET +{ + COND_NOT_SET = 0, + COND_REMOTE_SET = 0x1, + COND_LOCAL_SET = 0x2, + COND_AND_SET = 0x3, + COND_OR_SET = 0x4 +}; + +enum DUMP_OPT_ARG +{ + OPT_ARG_HOST = 256, + OPT_ARG_LOCAL_HOST, + OPT_ARG_REMOTE_HOST, + OPT_ARG_PORT, + OPT_ARG_LOCAL_PORT, + OPT_ARG_REMOTE_PORT, + OPT_ARG_MAC, + OPT_ARG_LOCAL_MAC, + OPT_ARG_REMOTE_MAC, + OPT_ARG_INVALID +}; + +typedef struct _ip_head +{ + u8 ihl:4; + u8 version:4; + u8 tos; + u16 tot_len; + u16 id; + u16 frag_off; + u8 ttl; + u8 protocol; + u16 chk_sum; + u32 local_ip; + u32 remote_ip; +} ip_head; + +typedef struct _tcp_head +{ + u16 src_port; + u16 dst_port; + u32 seq_no; + u32 ack_no; +} tcp_head; + +typedef struct _udp_head +{ + u16 src_port; + u16 dst_port; + u16 uhl; + u16 chk_sum; +} udp_head; + +typedef struct _dump_file_head +{ + u32 magic; + u16 major_ver; + u16 minor_ver; + u32 area; + u32 time_stamp; + u32 max_pack_size; + u32 link_type; +} dump_file_head; + +typedef struct _packet_head +{ + u32 sec; + u32 usec; + u32 save_len; + u32 org_len; +} packet_head; + +typedef struct _ip_addr_bits +{ + u32 addr_bits1; + u32 addr_bits2; + u32 addr_bits3; + u32 addr_bits4; +} ip_addr_bits; + +typedef struct _parse_msg_info +{ + u16 l2_protocol; // ARP/IP/OAM/LACP + u16 l3_protocol; // TCP/UDP/ICMP + u16 local_port; + u16 remote_port; + u32 local_ip; + u32 remote_ip; + char local_mac[MAC_ADDR_LEN + 1]; + char remote_mac[MAC_ADDR_LEN + 1]; + + void *org_msg; +} parse_msg_info; + +typedef struct _dump_condition +{ + bool has_condition; + u32 dump_count; + u32 dump_time; + u32 limit_len; + u16 direction; //1:send 2:recv 3:send-recv + u16 l2_protocol; // ARP/IP/OAM/LACP + u16 l3_protocol; // TCP/UDP/ICMP + u16 port_set_flag; + u16 port; + u16 local_port; + u16 remote_port; + u16 ip_set_flag; + u32 ip_addr; + u32 local_ip; + u32 remote_ip; + u16 mac_set_flag; + char mac_addr[MAC_ADDR_LEN + 1]; + char local_mac[MAC_ADDR_LEN + 1]; + char remote_mac[MAC_ADDR_LEN + 1]; + + char *dump_file_name; +} dump_condition; + +typedef struct _icmp_head +{ + u8 icmp_type; + u8 icmp_code; + u16 icmp_cksum; + u16 icmp_id; + u16 icmp_seq; + u32 timestamp; + + long icmp_sec; + long icmp_nsec; +} icmp_head; + +typedef struct _ning_input_info +{ + i32 send_count; // total send req + i32 retry_count; // retry count for 1 req + char src_ip[IP_ADDR_LEN]; + char dst_ip[IP_ADDR_LEN]; +} input_info; + +typedef struct _nping_stat_info +{ + u32 send_seq; + u32 recv_ok; + double all_interval; + double min_interval; + double max_interval; + struct timespec start_time; + struct timespec end_time; +} stat_info; + +#ifndef sys_sleep_ns +#define sys_sleep_ns(_s, _ns)\ +{ \ + if (_s >= 0 && _ns >= 0) \ + { \ + struct timespec delay, remain; \ + delay.tv_sec = _s; \ + delay.tv_nsec = _ns; \ + while (nanosleep(&delay, &remain) < 0) \ + { \ + delay = remain; \ + } \ + } \ +} +#endif + +#endif |