15#include <libmnl/libmnl.h>
17#include "internal/internal.h"
78 struct nf_conntrack *ct;
80 ct = malloc(
sizeof(
struct nf_conntrack));
84 memset(ct, 0,
sizeof(
struct nf_conntrack));
99 free(ct->helper_info);
101 nfct_bitmask_destroy(ct->connlabels);
102 if (ct->connlabels_mask)
103 nfct_bitmask_destroy(ct->connlabels_mask);
138 return sizeof(
struct nf_conntrack);
148struct nf_conntrack *
nfct_clone(
const struct nf_conntrack *ct)
150 struct nf_conntrack *clone;
173 if (unlikely(option > NFCT_SOPT_MAX)) {
178 return __setobjopt(ct, option);
193 if (unlikely(option > NFCT_GOPT_MAX)) {
198 return __getobjopt(ct, option);
225 enum nf_conntrack_msg_type type,
226 int (*cb)(
enum nf_conntrack_msg_type type,
227 struct nf_conntrack *ct,
231 struct __data_container *container;
235 container = malloc(
sizeof(
struct __data_container));
238 memset(container, 0,
sizeof(
struct __data_container));
242 container->type = type;
243 container->data = data;
245 h->nfnl_cb_ct.call = __callback;
246 h->nfnl_cb_ct.data = container;
247 h->nfnl_cb_ct.attr_count = CTA_MAX;
249 nfnl_callback_register(h->nfnlssh_ct,
253 nfnl_callback_register(h->nfnlssh_ct,
254 IPCTNL_MSG_CT_DELETE,
268 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
269 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
272 free(h->nfnl_cb_ct.data);
274 h->nfnl_cb_ct.call = NULL;
275 h->nfnl_cb_ct.data = NULL;
276 h->nfnl_cb_ct.attr_count = 0;
299 enum nf_conntrack_msg_type type,
300 int (*cb)(
const struct nlmsghdr *nlh,
301 enum nf_conntrack_msg_type type,
302 struct nf_conntrack *ct,
306 struct __data_container *container;
310 container = calloc(
sizeof(
struct __data_container), 1);
311 if (container == NULL)
316 container->type = type;
317 container->data = data;
319 h->nfnl_cb_ct.call = __callback;
320 h->nfnl_cb_ct.data = container;
321 h->nfnl_cb_ct.attr_count = CTA_MAX;
323 nfnl_callback_register(h->nfnlssh_ct,
327 nfnl_callback_register(h->nfnlssh_ct,
328 IPCTNL_MSG_CT_DELETE,
342 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
343 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
346 free(h->nfnl_cb_ct.data);
348 h->nfnl_cb_ct.call = NULL;
349 h->nfnl_cb_ct.data = NULL;
350 h->nfnl_cb_ct.attr_count = 0;
371 const void *value,
size_t len)
374 assert(value != NULL);
376 if (unlikely(type >= ATTR_MAX))
379 if (set_attr_array[type]) {
380 set_attr_array[type](ct, value, len);
381 set_bit(type, ct->head.set);
400 const enum nf_conntrack_attr type,
414 const enum nf_conntrack_attr type,
427 const enum nf_conntrack_attr type,
440 const enum nf_conntrack_attr type,
453 const enum nf_conntrack_attr type,
468 const enum nf_conntrack_attr type)
472 if (unlikely(type >= ATTR_MAX)) {
477 if (!test_bit(type, ct->head.set)) {
482 assert(get_attr_array[type]);
484 return get_attr_array[type](ct);
497 const enum nf_conntrack_attr type)
500 return ret == NULL ? 0 : *ret;
513 const enum nf_conntrack_attr type)
516 return ret == NULL ? 0 : *ret;
529 const enum nf_conntrack_attr type)
532 return ret == NULL ? 0 : *ret;
545 const enum nf_conntrack_attr type)
548 return ret == NULL ? 0 : *ret;
560 const enum nf_conntrack_attr type)
564 if (unlikely(type >= ATTR_MAX)) {
568 return test_bit(type, ct->head.set);
581 const enum nf_conntrack_attr *type_array,
588 for (i=0; i<size; i++) {
589 if (unlikely(type_array[i] >= ATTR_MAX)) {
593 if (!test_bit(type_array[i], ct->head.set))
608 const enum nf_conntrack_attr type)
612 if (unlikely(type >= ATTR_MAX)) {
616 unset_bit(type, ct->head.set);
631 const enum nf_conntrack_attr_grp type,
636 if (unlikely(type >= ATTR_GRP_MAX))
639 if (set_attr_grp_array[type]) {
640 set_attr_grp_array[type](ct, data);
641 set_bitmask_u32(ct->head.set,
642 attr_grp_bitmask[type].bitmask, __NFCT_BITSET);
656 const enum nf_conntrack_attr_grp type,
661 if (unlikely(type >= ATTR_GRP_MAX)) {
665 switch(attr_grp_bitmask[type].type) {
666 case NFCT_BITMASK_AND:
667 if (!test_bitmask_u32(ct->head.set,
668 attr_grp_bitmask[type].bitmask,
674 case NFCT_BITMASK_OR:
675 if (!test_bitmask_u32_or(ct->head.set,
676 attr_grp_bitmask[type].bitmask,
683 assert(get_attr_grp_array[type]);
684 get_attr_grp_array[type](ct, data);
696 const enum nf_conntrack_attr_grp type)
700 if (unlikely(type >= ATTR_GRP_MAX)) {
704 switch(attr_grp_bitmask[type].type) {
705 case NFCT_BITMASK_AND:
706 if (test_bitmask_u32(ct->head.set,
707 attr_grp_bitmask[type].bitmask,
712 case NFCT_BITMASK_OR:
713 if (test_bitmask_u32_or(ct->head.set,
714 attr_grp_bitmask[type].bitmask,
732 const enum nf_conntrack_attr_grp type)
736 if (unlikely(type >= ATTR_GRP_MAX)) {
740 unset_bitmask_u32(ct->head.set, attr_grp_bitmask[type].bitmask,
776 const struct nf_conntrack *ct)
782 return __build_conntrack(ssh, req, size, type, flags, ct);
785static void nfct_fill_hdr(
struct nfnlhdr *req, uint16_t type, uint16_t flags,
786 uint8_t l3num, uint8_t version)
788 char *buf = (
char *)&req->nlh;
789 struct nlmsghdr *nlh;
790 struct nfgenmsg *nfh;
792 nlh = mnl_nlmsg_put_header(buf);
793 nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | type;
794 nlh->nlmsg_flags = NLM_F_REQUEST | flags;
797 nfh = mnl_nlmsg_put_extra_header(nlh,
sizeof(
struct nfgenmsg));
798 nfh->nfgen_family = l3num;
799 nfh->version = version;
804__build_query_ct(
struct nfnl_subsys_handle *ssh,
805 const enum nf_conntrack_query qt,
806 const void *data,
void *buffer,
unsigned int size)
808 struct nfnlhdr *req = buffer;
809 const uint32_t *family = data;
812 assert(data != NULL);
815 memset(req, 0, size);
819 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
822 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK, data);
825 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
828 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_ACK, data);
831 nfct_fill_hdr(req, IPCTNL_MSG_CT_DELETE, NLM_F_ACK, *family,
834 case NFCT_Q_FLUSH_FILTER:
835 nfct_fill_hdr(req, IPCTNL_MSG_CT_DELETE, NLM_F_ACK, *family, 1);
838 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, *family,
841 case NFCT_Q_DUMP_RESET:
842 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
843 *family, NFNETLINK_V0);
845 case NFCT_Q_CREATE_UPDATE:
846 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data);
848 case NFCT_Q_DUMP_FILTER:
849 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, AF_UNSPEC,
851 __build_filter_dump(req, size, data);
853 case NFCT_Q_DUMP_FILTER_RESET:
854 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
855 AF_UNSPEC, NFNETLINK_V0);
856 __build_filter_dump(req, size, data);
902 const enum nf_conntrack_query qt,
907 return __build_query_ct(ssh, qt, data, buffer, size);
910static int __parse_message_type(
const struct nlmsghdr *nlh)
912 uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
913 uint16_t flags = nlh->nlmsg_flags;
914 int ret = NFCT_T_UNKNOWN;
916 if (type == IPCTNL_MSG_CT_NEW) {
917 if (flags & (NLM_F_CREATE|NLM_F_EXCL))
921 }
else if (type == IPCTNL_MSG_CT_DELETE)
922 ret = NFCT_T_DESTROY;
952 const struct nlmsghdr *nlh,
953 struct nf_conntrack *ct)
960 flags = __parse_message_type(nlh);
964 nfct_nlmsg_parse(nlh, ct);
988 const enum nf_conntrack_query qt,
991 const size_t size = 4096;
998 assert(data != NULL);
1000 if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1003 return nfnl_query(h->nfnlh, &u.req.nlh);
1020 const enum nf_conntrack_query qt,
1023 const size_t size = 4096;
1030 assert(data != NULL);
1032 if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1035 return nfnl_send(h->nfnlh, &u.req.nlh);
1057 return nfnl_catch(h->nfnlh);
1111 const struct nf_conntrack *ct,
1112 unsigned int msg_type,
1113 unsigned int out_type,
1116 assert(buf != NULL);
1120 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, NULL);
1139 const struct nf_conntrack *ct,
1140 unsigned int msg_type,
1141 unsigned int out_type,
1145 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, map);
1163 const struct nf_conntrack *ct2)
1165 assert(ct1 != NULL);
1166 assert(ct2 != NULL);
1168 return __compare(ct1, ct2, NFCT_CMP_ALL);
1209 const struct nf_conntrack *ct2,
1212 assert(ct1 != NULL);
1213 assert(ct2 != NULL);
1215 return __compare(ct1, ct2, flags);
1244 const struct nf_conntrack *ct2,
1249 assert(ct1 != NULL);
1250 assert(ct2 != NULL);
1252 if (flags & NFCT_CP_OVERRIDE) {
1253 __copy_fast(ct1, ct2);
1256 if (flags == NFCT_CP_ALL) {
1257 for (i=0; i<ATTR_MAX; i++) {
1258 if (test_bit(i, ct2->head.set)) {
1259 assert(copy_attr_array[i]);
1260 copy_attr_array[i](ct1, ct2);
1261 set_bit(i, ct1->head.set);
1267 static const int cp_orig_mask[] = {
1280 #define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int)
1282 if (flags & NFCT_CP_ORIG) {
1283 for (i=0; i<__CP_ORIG_MAX; i++) {
1284 if (test_bit(cp_orig_mask[i], ct2->head.set)) {
1285 assert(copy_attr_array[i]);
1286 copy_attr_array[cp_orig_mask[i]](ct1, ct2);
1287 set_bit(cp_orig_mask[i], ct1->head.set);
1292 static const int cp_repl_mask[] = {
1302 #define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int)
1304 if (flags & NFCT_CP_REPL) {
1305 for (i=0; i<__CP_REPL_MAX; i++) {
1306 if (test_bit(cp_repl_mask[i], ct2->head.set)) {
1307 assert(copy_attr_array[i]);
1308 copy_attr_array[cp_repl_mask[i]](ct1, ct2);
1309 set_bit(cp_repl_mask[i], ct1->head.set);
1314 if (flags & NFCT_CP_META) {
1315 for (i=ATTR_TCP_STATE; i<ATTR_MAX; i++) {
1316 if (test_bit(i, ct2->head.set)) {
1317 assert(copy_attr_array[i]),
1318 copy_attr_array[i](ct1, ct2);
1319 set_bit(i, ct1->head.set);
1334 const struct nf_conntrack *ct2,
1335 const enum nf_conntrack_attr type)
1337 if (test_bit(type, ct2->head.set)) {
1338 assert(copy_attr_array[type]);
1339 copy_attr_array[type](ct1, ct2);
1340 set_bit(type, ct1->head.set);
1362 return calloc(
sizeof(
struct nfct_filter), 1);
1375 assert(filter != NULL);
1390 const enum nfct_filter_attr type,
1393 assert(filter != NULL);
1394 assert(value != NULL);
1396 if (unlikely(type >= NFCT_FILTER_MAX))
1399 if (filter_attr_array[type]) {
1400 filter_attr_array[type](filter, value);
1401 set_bit(type, filter->set);
1414 const enum nfct_filter_attr type,
1436 const enum nfct_filter_attr type,
1437 const enum nfct_filter_logic logic)
1439 if (unlikely(type >= NFCT_FILTER_MAX)) {
1444 if (filter->logic[type]) {
1449 filter->logic[type] = logic;
1465 assert(filter != NULL);
1467 return __setup_netlink_socket_filter(fd, filter);
1480 return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &val,
sizeof(val));
1501 return calloc(
sizeof(
struct nfct_filter_dump), 1);
1512 assert(filter != NULL);
1524 const enum nfct_filter_dump_attr type,
1527 assert(filter_dump != NULL);
1528 assert(value != NULL);
1530 if (unlikely(type >= NFCT_FILTER_DUMP_MAX))
1533 if (set_filter_dump_attr_array[type]) {
1534 set_filter_dump_attr_array[type](filter_dump, value);
1535 filter_dump->set |= (1 << type);
1546 const enum nfct_filter_dump_attr type,
1570 return __labels_get_path();
1585 return __labelmap_get_name(m, bit);
1598 return __labelmap_get_bit(m, name);
1611 return __labelmap_new(mapfile);
1623 __labelmap_destroy(map);
1644struct nfct_bitmask *nfct_bitmask_new(
unsigned int max)
1646 struct nfct_bitmask *b;
1647 unsigned int bytes, words;
1652 words = DIV_ROUND_UP(max+1, 32);
1653 bytes = words *
sizeof(b->bits[0]);
1655 b = malloc(
sizeof(*b) + bytes);
1657 memset(b->bits, 0, bytes);
1670struct nfct_bitmask *nfct_bitmask_clone(
const struct nfct_bitmask *b)
1672 unsigned int bytes = b->words *
sizeof(b->bits[0]);
1673 struct nfct_bitmask *copy;
1675 bytes +=
sizeof(*b);
1677 copy = malloc(bytes);
1679 memcpy(copy, b, bytes);
1689void nfct_bitmask_set_bit(
struct nfct_bitmask *b,
unsigned int bit)
1691 unsigned int bits = b->words * 32;
1693 set_bit(bit, b->bits);
1704int nfct_bitmask_test_bit(
const struct nfct_bitmask *b,
unsigned int bit)
1706 unsigned int bits = b->words * 32;
1707 return bit < bits && test_bit(bit, b->bits);
1716void nfct_bitmask_unset_bit(
struct nfct_bitmask *b,
unsigned int bit)
1718 unsigned int bits = b->words * 32;
1720 unset_bit(bit, b->bits);
1728unsigned int nfct_bitmask_maxbit(
const struct nfct_bitmask *b)
1730 return (b->words * 32) - 1;
1745void nfct_bitmask_destroy(
struct nfct_bitmask *b)
1755void nfct_bitmask_clear(
struct nfct_bitmask *b)
1757 unsigned int bytes = b->words *
sizeof(b->bits[0]);
1758 memset(b->bits, 0, bytes);
1770bool nfct_bitmask_equal(
const struct nfct_bitmask *b1,
const struct nfct_bitmask *b2)
1772 if (b1->words != b2->words)
1775 return memcmp(b1->bits, b2->bits, b1->words *
sizeof(b1->bits[0])) == 0;
int nfct_callback_register(struct nfct_handle *h, enum nf_conntrack_msg_type type, int(*cb)(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data), void *data)
void nfct_callback_unregister2(struct nfct_handle *h)
void nfct_callback_unregister(struct nfct_handle *h)
int nfct_callback_register2(struct nfct_handle *h, enum nf_conntrack_msg_type type, int(*cb)(const struct nlmsghdr *nlh, enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data), void *data)
void nfct_filter_destroy(struct nfct_filter *filter)
int nfct_filter_detach(int fd)
int nfct_filter_set_logic(struct nfct_filter *filter, const enum nfct_filter_attr type, const enum nfct_filter_logic logic)
int nfct_filter_attach(int fd, struct nfct_filter *filter)
void nfct_filter_add_attr_u32(struct nfct_filter *filter, const enum nfct_filter_attr type, uint32_t value)
void nfct_filter_add_attr(struct nfct_filter *filter, const enum nfct_filter_attr type, const void *value)
struct nfct_filter * nfct_filter_create(void)
int nfct_send(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
int nfct_catch(struct nfct_handle *h)
int nfct_query(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
size_t nfct_sizeof(const struct nf_conntrack *ct)
int nfct_snprintf_labels(char *buf, unsigned int size, const struct nf_conntrack *ct, unsigned int msg_type, unsigned int out_type, unsigned int flags, struct nfct_labelmap *map)
void nfct_set_attr_u32(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint32_t value)
void nfct_destroy(struct nf_conntrack *ct)
void nfct_copy_attr(struct nf_conntrack *ct1, const struct nf_conntrack *ct2, const enum nf_conntrack_attr type)
void nfct_set_attr(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value)
int nfct_attr_grp_unset(struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type)
uint64_t nfct_get_attr_u64(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_setobjopt(struct nf_conntrack *ct, unsigned int option)
int nfct_get_attr_grp(const struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type, void *data)
void nfct_set_attr_grp(struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type, const void *data)
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_attr_is_set_array(const struct nf_conntrack *ct, const enum nf_conntrack_attr *type_array, int size)
int nfct_attr_unset(struct nf_conntrack *ct, const enum nf_conntrack_attr type)
void nfct_copy(struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags)
uint16_t nfct_get_attr_u16(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_attr_grp_is_set(const struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type)
int nfct_cmp(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags)
void nfct_set_attr_u16(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint16_t value)
uint32_t nfct_get_attr_u32(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
void nfct_set_attr_u8(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint8_t value)
void nfct_set_attr_u64(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint64_t value)
void nfct_set_attr_l(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value, size_t len)
int nfct_snprintf(char *buf, unsigned int size, const struct nf_conntrack *ct, unsigned int msg_type, unsigned int out_type, unsigned int flags)
size_t nfct_maxsize(void)
int nfct_attr_is_set(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_getobjopt(const struct nf_conntrack *ct, unsigned int option)
int nfct_compare(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2)
uint8_t nfct_get_attr_u8(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
struct nf_conntrack * nfct_new(void)
struct nf_conntrack * nfct_clone(const struct nf_conntrack *ct)
void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump, const enum nfct_filter_dump_attr type, uint8_t value)
struct nfct_filter_dump * nfct_filter_dump_create(void)
void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
void nfct_filter_dump_set_attr(struct nfct_filter_dump *filter_dump, const enum nfct_filter_dump_attr type, const void *value)
const char * nfct_labels_get_path(void)
void nfct_labelmap_destroy(struct nfct_labelmap *map)
const char * nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
struct nfct_labelmap * nfct_labelmap_new(const char *mapfile)
int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)
int nfct_parse_conntrack(enum nf_conntrack_msg_type type, const struct nlmsghdr *nlh, struct nf_conntrack *ct)
int nfct_build_conntrack(struct nfnl_subsys_handle *ssh, void *req, size_t size, uint16_t type, uint16_t flags, const struct nf_conntrack *ct)
int nfct_build_query(struct nfnl_subsys_handle *ssh, const enum nf_conntrack_query qt, const void *data, void *buffer, unsigned int size)