#include "ftp_decoder_inner.h" #include "ftp_decoder_hash.h" #include "ftp_decoder_util.h" #include #include #include static thread_local char __ftp_hash_string_buf[1024]; void ftp_declare_datalink_free(void *data) { struct ftp_context *fctx = (struct ftp_context *)data; ftp_parse_result_free(&fctx->parse_result); free(fctx); } static void ftp_declare_datalink_free_only_key(void *data) { return; // do nothing } int ftp_hash_add(void *handle, const void *key, u_int32_t key_len, void *value) { if (MESA_htable_add(handle, (const uint8_t *)key, key_len, value) < 0) { ftp_declare_datalink_free(value); return -1; } return 0; } void ftp_hash_del(void *handle, const struct ftp_link_key *hkey) { const void *key; u_int32_t key_len; if (SESSION_ADDR_TYPE_IPV4_TCP == hkey->addr_type || SESSION_ADDR_TYPE_IPV4_UDP == hkey->addr_type) { key = &hkey->tuplev4; key_len = sizeof(struct session_addr_ipv4); } else { key = &hkey->tuplev6; key_len = sizeof(struct session_addr_ipv6); } MESA_htable_del(handle, (const uint8_t *)key, key_len, ftp_declare_datalink_free_only_key); } void ftp_make_hkey_v4(struct session_addr_ipv4 *keyv4, uint32_t sip_net, uint32_t dip_net, uint16_t dip_port_net) { memset(keyv4, 0, sizeof(struct session_addr_ipv4)); keyv4->saddr = sip_net; keyv4->daddr = dip_net; keyv4->sport = 0; keyv4->dport = dip_port_net; } void ftp_make_hkey_v6(struct session_addr_ipv6 *keyv6, const struct in6_addr *sip, const struct in6_addr *dip, uint16_t dip_port_net) { memset(keyv6, 0, sizeof(struct session_addr_ipv6)); memcpy(keyv6->saddr, sip, IPV6_ADDR_LEN); memcpy(keyv6->daddr, dip, IPV6_ADDR_LEN); keyv6->sport = 0; keyv6->dport = dip_port_net; } int ftp_build_hashkey_from_session(struct session *sess, struct ftp_link_key *hkey) { enum session_addr_type saddr_type; struct session_addr *saddr = session_get0_addr(sess, &saddr_type); hkey->addr_type = saddr_type; if (SESSION_ADDR_TYPE_IPV4_TCP == saddr_type) { ftp_make_hkey_v4(&hkey->tuplev4, saddr->ipv4.saddr, saddr->ipv4.daddr, saddr->ipv4.dport); } else if (SESSION_ADDR_TYPE_IPV6_TCP == saddr_type) { ftp_make_hkey_v6(&hkey->tuplev6, (struct in6_addr *)saddr->ipv6.saddr, (struct in6_addr *)saddr->ipv6.daddr, saddr->ipv6.dport); } else { return -1; } return 0; } void *ftp_hash_search(void *handle, const struct ftp_link_key *hkey) { const void *key; u_int32_t key_len; if (SESSION_ADDR_TYPE_IPV4_TCP == hkey->addr_type || SESSION_ADDR_TYPE_IPV4_UDP == hkey->addr_type) { key = &hkey->tuplev4; key_len = sizeof(struct session_addr_ipv4); } else { key = &hkey->tuplev6; key_len = sizeof(struct session_addr_ipv6); } return MESA_htable_search(handle, (const uint8_t *)key, key_len); } const char *ftp_hash_key_to_str(const struct ftp_link_key *hkey) { char sip_str[INET6_ADDRSTRLEN], dip_str[INET6_ADDRSTRLEN]; unsigned short sport_host, dport_host; if (SESSION_ADDR_TYPE_IPV4_TCP == hkey->addr_type || SESSION_ADDR_TYPE_IPV4_UDP == hkey->addr_type) { inet_ntop(AF_INET, &hkey->tuplev4.saddr, sip_str, INET_ADDRSTRLEN); inet_ntop(AF_INET, &hkey->tuplev4.daddr, dip_str, INET_ADDRSTRLEN); sport_host = ntohs(hkey->tuplev4.sport); dport_host = ntohs(hkey->tuplev4.dport); } else { inet_ntop(AF_INET, hkey->tuplev6.saddr, sip_str, INET6_ADDRSTRLEN); inet_ntop(AF_INET, hkey->tuplev6.daddr, dip_str, INET6_ADDRSTRLEN); sport_host = ntohs(hkey->tuplev6.sport); dport_host = ntohs(hkey->tuplev6.dport); } snprintf(__ftp_hash_string_buf, sizeof(__ftp_hash_string_buf), "%s:%u -> %s:%u", sip_str, sport_host, dip_str, dport_host); return __ftp_hash_string_buf; } int ftp_hash_table_create(struct ftp_decoder_env *fenv) { int opt, opt_len; fenv->data_link_table = (void **)calloc(fenv->thread_count, sizeof(void *)); for (int i = 0; i < fenv->thread_count; i++) { fenv->data_link_table[i] = MESA_htable_born(); assert(fenv->data_link_table[i]); opt = 4096; opt_len = sizeof(int); MESA_htable_set_opt(fenv->data_link_table[i], MHO_HASH_SLOT_SIZE, &opt, opt_len); opt = 0; opt_len = sizeof(int); MESA_htable_set_opt(fenv->data_link_table[i], MHO_THREAD_SAFE, &opt, opt_len); opt = 0; opt_len = sizeof(int); MESA_htable_set_opt(fenv->data_link_table[i], MHO_SCREEN_PRINT_CTRL, &opt, opt_len); opt = 10; opt_len = sizeof(int); MESA_htable_set_opt(fenv->data_link_table[i], MHO_EXPIRE_TIME, &opt, opt_len); MESA_htable_set_opt(fenv->data_link_table[i], MHO_CBFUN_DATA_FREE, (void *)&ftp_declare_datalink_free, sizeof(void *)); MESA_htable_mature(fenv->data_link_table[i]); } return 0; } void ftp_hash_table_destroy(struct ftp_decoder_env *fenv) { unsigned int remain_items; for (int i = 0; i < fenv->thread_count; i++) { remain_items = MESA_htable_get_elem_num(fenv->data_link_table[0]); if (remain_items > 0) { ftp_runtime_log(RLOG_LV_DEBUG, "ftp_hash_table_destroy(): thread:%d declare datalink table remain items:%u\n", i, remain_items); } MESA_htable_destroy(fenv->data_link_table[i], ftp_declare_datalink_free); } free(fenv->data_link_table); }