create_un_nat_conn(struct conntrack *ct, struct conn *conn_for_un_nat_copy,
                   long long now, bool alg_un_nat)
{
    struct conn *nc = xmemdup(conn_for_un_nat_copy, sizeof *nc);
    nc->key = conn_for_un_nat_copy->rev_key;
    nc->rev_key = conn_for_un_nat_copy->key;
    uint32_t un_nat_hash = conn_key_hash(&nc->key, ct->hash_basis);
    unsigned un_nat_conn_bucket = hash_to_bucket(un_nat_hash);
    ct_lock_lock(&ct->buckets[un_nat_conn_bucket].lock);
    struct conn *rev_conn = conn_lookup(ct, &nc->key, now);

    if (alg_un_nat) {
        if (!rev_conn) {
            hmap_insert(&ct->buckets[un_nat_conn_bucket].connections,
                        &nc->node, un_nat_hash);
        } else {
            char *log_msg = xasprintf("Unusual condition for un_nat conn "
                                      "create for alg: rev_conn %p", rev_conn);
            ct_print_conn_info(nc, log_msg, VLL_INFO, true, false);
            free(log_msg);
            free(nc);
        }
    } else {
        ct_rwlock_rdlock(&ct->resources_lock);

        struct nat_conn_key_node *nat_conn_key_node =
            nat_conn_keys_lookup(&ct->nat_conn_keys, &nc->key, ct->hash_basis);
        if (nat_conn_key_node && !conn_key_cmp(&nat_conn_key_node->value,
            &nc->rev_key) && !rev_conn) {

            hmap_insert(&ct->buckets[un_nat_conn_bucket].connections,
                        &nc->node, un_nat_hash);
        } else {
            char *log_msg = xasprintf("Unusual condition for un_nat conn "
                                      "create: nat_conn_key_node/rev_conn "
                                      "%p/%p", nat_conn_key_node, rev_conn);
            ct_print_conn_info(nc, log_msg, VLL_INFO, true, false);
            free(log_msg);
            free(nc);
        }
        ct_rwlock_unlock(&ct->resources_lock);
    }
    ct_lock_unlock(&ct->buckets[un_nat_conn_bucket].lock);
}
create_un_nat_conn(struct conntrack *ct, struct conn *conn_for_un_nat_copy,
                   long long now, bool alg_un_nat)
{
    struct conn *nc = xmemdup(conn_for_un_nat_copy, sizeof *nc);
    nc->key = conn_for_un_nat_copy->rev_key;
    nc->rev_key = conn_for_un_nat_copy->key;
    uint32_t un_nat_hash = conn_key_hash(&nc->key, ct->hash_basis);
    unsigned un_nat_conn_bucket = hash_to_bucket(un_nat_hash);
    ct_lock_lock(&ct->buckets[un_nat_conn_bucket].lock);
    struct conn *rev_conn = conn_lookup(ct, &nc->key, now);

    if (alg_un_nat) {
        if (!rev_conn) {
            hmap_insert(&ct->buckets[un_nat_conn_bucket].connections,
                        &nc->node, un_nat_hash);
        } else {
            char *log_msg = xasprintf("Unusual condition for un_nat conn "
                                      "create for alg: rev_conn %p", rev_conn);
            ct_print_conn_info(nc, log_msg, VLL_INFO, true, false);
            free(log_msg);
            free(nc);
        }
    } else {
        ct_rwlock_rdlock(&ct->resources_lock);

        struct nat_conn_key_node *nat_conn_key_node =
            nat_conn_keys_lookup(&ct->nat_conn_keys, &nc->key, ct->hash_basis);
        if (nat_conn_key_node && !conn_key_cmp(&nat_conn_key_node->value,
            &nc->rev_key) && !rev_conn) {

            hmap_insert(&ct->buckets[un_nat_conn_bucket].connections,
                        &nc->node, un_nat_hash);
        } else {
            char *log_msg = xasprintf("Unusual condition for un_nat conn "
                                      "create: nat_conn_key_node/rev_conn "
                                      "%p/%p", nat_conn_key_node, rev_conn);
            ct_print_conn_info(nc, log_msg, VLL_INFO, true, false);
            free(log_msg);
            free(nc);
        }
        ct_rwlock_unlock(&ct->resources_lock);
    }
    ct_lock_unlock(&ct->buckets[un_nat_conn_bucket].lock);
}