summaryrefslogtreecommitdiffstats
path: root/stacks/lwip_stack/tools
diff options
context:
space:
mode:
authorsatish.karunanithi <satish.fdio@gmail.com>2018-08-13 19:39:55 +0530
committersatish.karunanithi <satish.fdio@gmail.com>2018-08-14 10:22:59 +0530
commit54f5a270c74c405d3bb0e15d5b69d6d0e1e96c49 (patch)
treea855ebf120dd46c50784c30a53a1bdf9aedea632 /stacks/lwip_stack/tools
parentbd6e75c243db1b384ba0882ecaf9063ec4cd70bd (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.txt91
-rw-r--r--stacks/lwip_stack/tools/nping.c627
-rw-r--r--stacks/lwip_stack/tools/ntcpdump.c1368
-rw-r--r--stacks/lwip_stack/tools/tool_common.h243
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