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);
148 struct 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);
785 static 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,
835 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, *family,
838 case NFCT_Q_DUMP_RESET:
839 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
840 *family, NFNETLINK_V0);
842 case NFCT_Q_CREATE_UPDATE:
843 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data);
845 case NFCT_Q_DUMP_FILTER:
846 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, AF_UNSPEC,
848 __build_filter_dump(req, size, data);
850 case NFCT_Q_DUMP_FILTER_RESET:
851 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
852 AF_UNSPEC, NFNETLINK_V0);
853 __build_filter_dump(req, size, data);
899 const enum nf_conntrack_query qt,
904 return __build_query_ct(ssh, qt, data, buffer, size);
907 static int __parse_message_type(
const struct nlmsghdr *nlh)
909 uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
910 uint16_t flags = nlh->nlmsg_flags;
911 int ret = NFCT_T_UNKNOWN;
913 if (type == IPCTNL_MSG_CT_NEW) {
914 if (flags & (NLM_F_CREATE|NLM_F_EXCL))
918 }
else if (type == IPCTNL_MSG_CT_DELETE)
919 ret = NFCT_T_DESTROY;
949 const struct nlmsghdr *nlh,
950 struct nf_conntrack *ct)
957 flags = __parse_message_type(nlh);
961 nfct_nlmsg_parse(nlh, ct);
985 const enum nf_conntrack_query qt,
988 const size_t size = 4096;
995 assert(data != NULL);
997 if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1000 return nfnl_query(h->nfnlh, &u.req.nlh);
1017 const enum nf_conntrack_query qt,
1020 const size_t size = 4096;
1027 assert(data != NULL);
1029 if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1032 return nfnl_send(h->nfnlh, &u.req.nlh);
1054 return nfnl_catch(h->nfnlh);
1108 const struct nf_conntrack *ct,
1109 unsigned int msg_type,
1110 unsigned int out_type,
1113 assert(buf != NULL);
1117 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, NULL);
1136 const struct nf_conntrack *ct,
1137 unsigned int msg_type,
1138 unsigned int out_type,
1142 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, map);
1160 const struct nf_conntrack *ct2)
1162 assert(ct1 != NULL);
1163 assert(ct2 != NULL);
1165 return __compare(ct1, ct2, NFCT_CMP_ALL);
1206 const struct nf_conntrack *ct2,
1209 assert(ct1 != NULL);
1210 assert(ct2 != NULL);
1212 return __compare(ct1, ct2, flags);
1241 const struct nf_conntrack *ct2,
1246 assert(ct1 != NULL);
1247 assert(ct2 != NULL);
1249 if (flags & NFCT_CP_OVERRIDE) {
1250 __copy_fast(ct1, ct2);
1253 if (flags == NFCT_CP_ALL) {
1254 for (i=0; i<ATTR_MAX; i++) {
1255 if (test_bit(i, ct2->head.set)) {
1256 assert(copy_attr_array[i]);
1257 copy_attr_array[i](ct1, ct2);
1258 set_bit(i, ct1->head.set);
1264 static const int cp_orig_mask[] = {
1277 #define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int)
1279 if (flags & NFCT_CP_ORIG) {
1280 for (i=0; i<__CP_ORIG_MAX; i++) {
1281 if (test_bit(cp_orig_mask[i], ct2->head.set)) {
1282 assert(copy_attr_array[i]);
1283 copy_attr_array[cp_orig_mask[i]](ct1, ct2);
1284 set_bit(cp_orig_mask[i], ct1->head.set);
1289 static const int cp_repl_mask[] = {
1299 #define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int)
1301 if (flags & NFCT_CP_REPL) {
1302 for (i=0; i<__CP_REPL_MAX; i++) {
1303 if (test_bit(cp_repl_mask[i], ct2->head.set)) {
1304 assert(copy_attr_array[i]);
1305 copy_attr_array[cp_repl_mask[i]](ct1, ct2);
1306 set_bit(cp_repl_mask[i], ct1->head.set);
1311 if (flags & NFCT_CP_META) {
1312 for (i=ATTR_TCP_STATE; i<ATTR_MAX; i++) {
1313 if (test_bit(i, ct2->head.set)) {
1314 assert(copy_attr_array[i]),
1315 copy_attr_array[i](ct1, ct2);
1316 set_bit(i, ct1->head.set);
1331 const struct nf_conntrack *ct2,
1332 const enum nf_conntrack_attr type)
1334 if (test_bit(type, ct2->head.set)) {
1335 assert(copy_attr_array[type]);
1336 copy_attr_array[type](ct1, ct2);
1337 set_bit(type, ct1->head.set);
1359 return calloc(
sizeof(
struct nfct_filter), 1);
1372 assert(filter != NULL);
1387 const enum nfct_filter_attr type,
1390 assert(filter != NULL);
1391 assert(value != NULL);
1393 if (unlikely(type >= NFCT_FILTER_MAX))
1396 if (filter_attr_array[type]) {
1397 filter_attr_array[type](filter, value);
1398 set_bit(type, filter->set);
1411 const enum nfct_filter_attr type,
1433 const enum nfct_filter_attr type,
1434 const enum nfct_filter_logic logic)
1436 if (unlikely(type >= NFCT_FILTER_MAX)) {
1441 if (filter->logic[type]) {
1446 filter->logic[type] = logic;
1462 assert(filter != NULL);
1464 return __setup_netlink_socket_filter(fd, filter);
1477 return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &val,
sizeof(val));
1498 return calloc(
sizeof(
struct nfct_filter_dump), 1);
1509 assert(filter != NULL);
1521 const enum nfct_filter_dump_attr type,
1524 assert(filter_dump != NULL);
1525 assert(value != NULL);
1527 if (unlikely(type >= NFCT_FILTER_DUMP_MAX))
1530 if (set_filter_dump_attr_array[type]) {
1531 set_filter_dump_attr_array[type](filter_dump, value);
1532 filter_dump->set |= (1 << type);
1543 const enum nfct_filter_dump_attr type,
1567 return __labels_get_path();
1582 return __labelmap_get_name(m, bit);
1595 return __labelmap_get_bit(m, name);
1608 return __labelmap_new(mapfile);
1620 __labelmap_destroy(map);
1641 struct nfct_bitmask *nfct_bitmask_new(
unsigned int max)
1643 struct nfct_bitmask *b;
1644 unsigned int bytes, words;
1649 words = DIV_ROUND_UP(max+1, 32);
1650 bytes = words *
sizeof(b->bits[0]);
1652 b = malloc(
sizeof(*b) + bytes);
1654 memset(b->bits, 0, bytes);
1667 struct nfct_bitmask *nfct_bitmask_clone(
const struct nfct_bitmask *b)
1669 unsigned int bytes = b->words *
sizeof(b->bits[0]);
1670 struct nfct_bitmask *copy;
1672 bytes +=
sizeof(*b);
1674 copy = malloc(bytes);
1676 memcpy(copy, b, bytes);
1686 void nfct_bitmask_set_bit(
struct nfct_bitmask *b,
unsigned int bit)
1688 unsigned int bits = b->words * 32;
1690 set_bit(bit, b->bits);
1701 int nfct_bitmask_test_bit(
const struct nfct_bitmask *b,
unsigned int bit)
1703 unsigned int bits = b->words * 32;
1704 return bit < bits && test_bit(bit, b->bits);
1713 void nfct_bitmask_unset_bit(
struct nfct_bitmask *b,
unsigned int bit)
1715 unsigned int bits = b->words * 32;
1717 unset_bit(bit, b->bits);
1725 unsigned int nfct_bitmask_maxbit(
const struct nfct_bitmask *b)
1727 return (b->words * 32) - 1;
1742 void nfct_bitmask_destroy(
struct nfct_bitmask *b)
1752 void nfct_bitmask_clear(
struct nfct_bitmask *b)
1754 unsigned int bytes = b->words *
sizeof(b->bits[0]);
1755 memset(b->bits, 0, bytes);
1767 bool nfct_bitmask_equal(
const struct nfct_bitmask *b1,
const struct nfct_bitmask *b2)
1769 if (b1->words != b2->words)
1772 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)
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
struct nf_conntrack * nfct_new(void)
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)
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)
struct nf_conntrack * nfct_clone(const struct nf_conntrack *ct)
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)
void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump, const enum nfct_filter_dump_attr type, uint8_t value)
void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
struct nfct_filter_dump * nfct_filter_dump_create(void)
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_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
struct nfct_labelmap * nfct_labelmap_new(const char *mapfile)
void nfct_labelmap_destroy(struct nfct_labelmap *map)
const char * nfct_labels_get_path(void)
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)