/* * * 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 #include #include #include #include #include #include #include #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; }