summaryrefslogtreecommitdiff
path: root/src/ftp_decoder_hash.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ftp_decoder_hash.cpp')
-rw-r--r--src/ftp_decoder_hash.cpp169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/ftp_decoder_hash.cpp b/src/ftp_decoder_hash.cpp
new file mode 100644
index 0000000..752505c
--- /dev/null
+++ b/src/ftp_decoder_hash.cpp
@@ -0,0 +1,169 @@
+#include "ftp_decoder_inner.h"
+#include "ftp_decoder_hash.h"
+#include "ftp_decoder_util.h"
+#include <MESA_htable.h>
+#include <cstdint>
+#include <arpa/inet.h>
+
+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);
+} \ No newline at end of file