// ----------------------------------------------------------------------------------;
// michael.mill@metacom.net --- (12/09/2018)
//
// https://github.com/threatstack/libnetfilter_conntrack/tree/master/utils
// https://groups.google.com/forum/#!topic/netsniff-ng/27XLHawhxJs
// https://gist.github.com/guillaumerose/907377
// https://www.systutorials.com/docs/linux/man/8-conntrack/
//
// install : libnetfilter-conntrack-dev
//         : libnetfilter-queue-dev

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <stdarg.h>

#include <string>
#include <iostream>

#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>

// ----------------------------------------------------------------------------------;

struct cb_delete_t {

    struct nfct_handle *ith;
    u_int32_t           ip;
};

struct nfct_handle *ith;

// ----------------------------------------------------------------------------------;

static int cb(enum   nf_conntrack_msg_type type,
	          struct nf_conntrack *ct,
	          void  *data) {

    cb_delete_t * info = (cb_delete_t*) data;

    u_int32_t src = nfct_get_attr_u32(ct, ATTR_IPV4_SRC);
    u_int32_t dst = nfct_get_attr_u32(ct, ATTR_IPV4_DST);

    // debug! ---------------------------------------------------------------;
    // src, dst, info-ip
    // 
    // EILSEQ
    // Illegal sequence of bytes (for example, in an MBCS string).
    //
    // "Invalid or incomplete multibyte or wide character"
    //

    struct in_addr ip_addr_src;
    struct in_addr ip_addr_dst;

    ip_addr_src.s_addr = src;
    ip_addr_dst.s_addr = dst;

    // debug! ---------------------------------------------------------------;

    if (info->ip != src && info->ip != dst) {
        return NFCT_CB_CONTINUE;
    }

    int res;

    //printf("ip - ip : %s %s\n", inet_ntoa(ip_addr_src), inet_ntoa(ip_addr_dst));

    res = nfct_query(info->ith, NFCT_Q_DESTROY, ct);

    if (res == -1) {

        printf("[%d][%s]\n", res, strerror(errno));
        return -1;
    }
    return NFCT_CB_CONTINUE;
}

// ----------------------------------------------------------------------------------;

int ipset_conntrack (std::string conntrack_ip) {

    cb_delete_t * cb_t = new cb_delete_t();

    struct nfct_handle *cth = nfct_open(CONNTRACK, 0);

    cb_t->ip  = inet_addr(conntrack_ip.c_str());
    cb_t->ith = nfct_open(CONNTRACK, 0);

    if (!cb_t->ith) {
        perror("nfct_open");
        return -1;
    }

    nfct_callback_register(cth, NFCT_T_ALL, cb, cb_t);

	struct nfct_filter_dump * filter_dump = nfct_filter_dump_create();

	if (filter_dump == NULL) {
        perror("filter_dump");
        return -1;
    }

	int res = nfct_query(cth, NFCT_Q_DUMP_FILTER, filter_dump);

    nfct_filter_dump_destroy(filter_dump);

    nfct_close(cb_t->ith);
	nfct_close(cth);

    delete cb_t;

    return 1;
}
