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(1,
sizeof(
struct __data_container));
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 memset(req, 0, size);
784 return __build_conntrack(req, size, type, flags, ct);
787static void nfct_fill_hdr(
struct nfnlhdr *req, uint16_t type, uint16_t flags,
788 uint8_t l3num, uint8_t version)
790 char *buf = (
char *)&req->nlh;
791 struct nlmsghdr *nlh;
792 struct nfgenmsg *nfh;
794 nlh = mnl_nlmsg_put_header(buf);
795 nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | type;
796 nlh->nlmsg_flags = NLM_F_REQUEST | flags;
799 nfh = mnl_nlmsg_put_extra_header(nlh,
sizeof(
struct nfgenmsg));
800 nfh->nfgen_family = l3num;
801 nfh->version = version;
806__build_query_ct(
const enum nf_conntrack_query qt,
807 const void *data,
void *buffer,
unsigned int size)
809 struct nfnlhdr *req = buffer;
810 const uint32_t *family = data;
812 assert(data != NULL);
815 memset(buffer, 0, size);
819 __build_conntrack(req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
822 __build_conntrack(req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK, data);
825 __build_conntrack(req, size, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
828 __build_conntrack(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);
836 if (__build_filter_flush(req, size, data) < 0)
840 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, *family,
843 case NFCT_Q_DUMP_RESET:
844 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
845 *family, NFNETLINK_V0);
847 case NFCT_Q_CREATE_UPDATE:
848 __build_conntrack(req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data);
850 case NFCT_Q_DUMP_FILTER:
851 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, AF_UNSPEC,
853 if (__build_filter_dump(req, size, data) < 0)
856 case NFCT_Q_DUMP_FILTER_RESET:
857 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
858 AF_UNSPEC, NFNETLINK_V0);
859 if (__build_filter_dump(req, size, data) < 0)
906 const enum nf_conntrack_query qt,
911 return __build_query_ct(qt, data, buffer, size);
914static int __parse_message_type(
const struct nlmsghdr *nlh)
916 uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
917 uint16_t flags = nlh->nlmsg_flags;
918 int ret = NFCT_T_UNKNOWN;
920 if (type == IPCTNL_MSG_CT_NEW) {
921 if (flags & (NLM_F_CREATE|NLM_F_EXCL))
925 }
else if (type == IPCTNL_MSG_CT_DELETE)
926 ret = NFCT_T_DESTROY;
956 const struct nlmsghdr *nlh,
957 struct nf_conntrack *ct)
964 flags = __parse_message_type(nlh);
968 nfct_nlmsg_parse(nlh, ct);
992 const enum nf_conntrack_query qt,
995 const size_t size = 4096;
1002 assert(data != NULL);
1004 if (__build_query_ct(qt, data, &u.req, size) == -1)
1007 return nfnl_query(h->nfnlh, &u.req.nlh);
1024 const enum nf_conntrack_query qt,
1027 const size_t size = 4096;
1034 assert(data != NULL);
1036 if (__build_query_ct(qt, data, &u.req, size) == -1)
1039 return nfnl_send(h->nfnlh, &u.req.nlh);
1061 return nfnl_catch(h->nfnlh);
1115 const struct nf_conntrack *ct,
1116 unsigned int msg_type,
1117 unsigned int out_type,
1120 assert(buf != NULL);
1124 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, NULL);
1143 const struct nf_conntrack *ct,
1144 unsigned int msg_type,
1145 unsigned int out_type,
1149 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, map);
1167 const struct nf_conntrack *ct2)
1169 assert(ct1 != NULL);
1170 assert(ct2 != NULL);
1172 return __compare(ct1, ct2, NFCT_CMP_ALL);
1213 const struct nf_conntrack *ct2,
1216 assert(ct1 != NULL);
1217 assert(ct2 != NULL);
1219 return __compare(ct1, ct2, flags);
1248 const struct nf_conntrack *ct2,
1253 assert(ct1 != NULL);
1254 assert(ct2 != NULL);
1256 if (flags & NFCT_CP_OVERRIDE) {
1257 __copy_fast(ct1, ct2);
1260 if (flags == NFCT_CP_ALL) {
1261 for (i=0; i<ATTR_MAX; i++) {
1262 if (test_bit(i, ct2->head.set)) {
1263 assert(copy_attr_array[i]);
1264 copy_attr_array[i](ct1, ct2);
1265 set_bit(i, ct1->head.set);
1271 static const int cp_orig_mask[] = {
1284 #define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int)
1286 if (flags & NFCT_CP_ORIG) {
1287 for (i=0; i<__CP_ORIG_MAX; i++) {
1288 if (test_bit(cp_orig_mask[i], ct2->head.set)) {
1289 assert(copy_attr_array[i]);
1290 copy_attr_array[cp_orig_mask[i]](ct1, ct2);
1291 set_bit(cp_orig_mask[i], ct1->head.set);
1296 static const int cp_repl_mask[] = {
1306 #define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int)
1308 if (flags & NFCT_CP_REPL) {
1309 for (i=0; i<__CP_REPL_MAX; i++) {
1310 if (test_bit(cp_repl_mask[i], ct2->head.set)) {
1311 assert(copy_attr_array[i]);
1312 copy_attr_array[cp_repl_mask[i]](ct1, ct2);
1313 set_bit(cp_repl_mask[i], ct1->head.set);
1318 if (flags & NFCT_CP_META) {
1319 for (i=ATTR_TCP_STATE; i<ATTR_MAX; i++) {
1320 if (test_bit(i, ct2->head.set)) {
1321 assert(copy_attr_array[i]),
1322 copy_attr_array[i](ct1, ct2);
1323 set_bit(i, ct1->head.set);
1338 const struct nf_conntrack *ct2,
1339 const enum nf_conntrack_attr type)
1341 if (test_bit(type, ct2->head.set)) {
1342 assert(copy_attr_array[type]);
1343 copy_attr_array[type](ct1, ct2);
1344 set_bit(type, ct1->head.set);
1366 return calloc(1,
sizeof(
struct nfct_filter));
1379 assert(filter != NULL);
1394 const enum nfct_filter_attr type,
1397 assert(filter != NULL);
1398 assert(value != NULL);
1400 if (unlikely(type >= NFCT_FILTER_MAX))
1403 if (filter_attr_array[type]) {
1404 filter_attr_array[type](filter, value);
1405 set_bit(type, filter->set);
1418 const enum nfct_filter_attr type,
1440 const enum nfct_filter_attr type,
1441 const enum nfct_filter_logic logic)
1443 if (unlikely(type >= NFCT_FILTER_MAX)) {
1448 if (filter->logic[type]) {
1453 filter->logic[type] = logic;
1469 assert(filter != NULL);
1471 return __setup_netlink_socket_filter(fd, filter);
1484 return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &val,
sizeof(val));
1505 return calloc(1,
sizeof(
struct nfct_filter_dump));
1516 assert(filter != NULL);
1528 const enum nfct_filter_dump_attr type,
1531 assert(filter_dump != NULL);
1532 assert(value != NULL);
1534 if (unlikely(type >= NFCT_FILTER_DUMP_MAX))
1537 if (set_filter_dump_attr_array[type]) {
1538 set_filter_dump_attr_array[type](filter_dump, value);
1539 filter_dump->set |= (1 << type);
1550 const enum nfct_filter_dump_attr type,
1563 const enum nfct_filter_dump_attr type,
1587 return __labels_get_path();
1602 return __labelmap_get_name(m, bit);
1615 return __labelmap_get_bit(m, name);
1628 return __labelmap_new(mapfile);
1640 __labelmap_destroy(map);
1661struct nfct_bitmask *nfct_bitmask_new(
unsigned int max)
1663 struct nfct_bitmask *b;
1664 unsigned int bytes, words;
1669 words = DIV_ROUND_UP(max+1, 32);
1670 bytes = words *
sizeof(b->bits[0]);
1672 b = malloc(
sizeof(*b) + bytes);
1674 memset(b->bits, 0, bytes);
1687struct nfct_bitmask *nfct_bitmask_clone(
const struct nfct_bitmask *b)
1689 unsigned int bytes = b->words *
sizeof(b->bits[0]);
1690 struct nfct_bitmask *copy;
1692 bytes +=
sizeof(*b);
1694 copy = malloc(bytes);
1696 memcpy(copy, b, bytes);
1706void nfct_bitmask_set_bit(
struct nfct_bitmask *b,
unsigned int bit)
1708 unsigned int bits = b->words * 32;
1710 set_bit(bit, b->bits);
1721int nfct_bitmask_test_bit(
const struct nfct_bitmask *b,
unsigned int bit)
1723 unsigned int bits = b->words * 32;
1724 return bit < bits && test_bit(bit, b->bits);
1733void nfct_bitmask_unset_bit(
struct nfct_bitmask *b,
unsigned int bit)
1735 unsigned int bits = b->words * 32;
1737 unset_bit(bit, b->bits);
1745unsigned int nfct_bitmask_maxbit(
const struct nfct_bitmask *b)
1747 return (b->words * 32) - 1;
1762void nfct_bitmask_destroy(
struct nfct_bitmask *b)
1772void nfct_bitmask_clear(
struct nfct_bitmask *b)
1774 unsigned int bytes = b->words *
sizeof(b->bits[0]);
1775 memset(b->bits, 0, bytes);
1787bool nfct_bitmask_equal(
const struct nfct_bitmask *b1,
const struct nfct_bitmask *b2)
1789 if (b1->words != b2->words)
1792 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_u16(struct nfct_filter_dump *filter_dump, const enum nfct_filter_dump_attr type, uint16_t value)
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)