16 #include "internal/internal.h"
77 struct nf_conntrack *ct;
79 ct = malloc(
sizeof(
struct nf_conntrack));
83 memset(ct, 0,
sizeof(
struct nf_conntrack));
98 free(ct->helper_info);
100 nfct_bitmask_destroy(ct->connlabels);
101 if (ct->connlabels_mask)
102 nfct_bitmask_destroy(ct->connlabels_mask);
137 return sizeof(
struct nf_conntrack);
147 struct nf_conntrack *
nfct_clone(
const struct nf_conntrack *ct)
149 struct nf_conntrack *clone;
172 if (unlikely(option > NFCT_SOPT_MAX)) {
177 return __setobjopt(ct, option);
192 if (unlikely(option > NFCT_GOPT_MAX)) {
197 return __getobjopt(ct, option);
224 enum nf_conntrack_msg_type type,
225 int (*cb)(
enum nf_conntrack_msg_type type,
226 struct nf_conntrack *ct,
230 struct __data_container *container;
234 container = malloc(
sizeof(
struct __data_container));
237 memset(container, 0,
sizeof(
struct __data_container));
241 container->type = type;
242 container->data = data;
244 h->nfnl_cb_ct.call = __callback;
245 h->nfnl_cb_ct.data = container;
246 h->nfnl_cb_ct.attr_count = CTA_MAX;
248 nfnl_callback_register(h->nfnlssh_ct,
252 nfnl_callback_register(h->nfnlssh_ct,
253 IPCTNL_MSG_CT_DELETE,
267 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
268 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
271 free(h->nfnl_cb_ct.data);
273 h->nfnl_cb_ct.call = NULL;
274 h->nfnl_cb_ct.data = NULL;
275 h->nfnl_cb_ct.attr_count = 0;
298 enum nf_conntrack_msg_type type,
299 int (*cb)(
const struct nlmsghdr *nlh,
300 enum nf_conntrack_msg_type type,
301 struct nf_conntrack *ct,
305 struct __data_container *container;
309 container = calloc(
sizeof(
struct __data_container), 1);
310 if (container == NULL)
315 container->type = type;
316 container->data = data;
318 h->nfnl_cb_ct.call = __callback;
319 h->nfnl_cb_ct.data = container;
320 h->nfnl_cb_ct.attr_count = CTA_MAX;
322 nfnl_callback_register(h->nfnlssh_ct,
326 nfnl_callback_register(h->nfnlssh_ct,
327 IPCTNL_MSG_CT_DELETE,
341 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
342 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
345 free(h->nfnl_cb_ct.data);
347 h->nfnl_cb_ct.call = NULL;
348 h->nfnl_cb_ct.data = NULL;
349 h->nfnl_cb_ct.attr_count = 0;
370 const void *value,
size_t len)
373 assert(value != NULL);
375 if (unlikely(type >= ATTR_MAX))
378 if (set_attr_array[type]) {
379 set_attr_array[type](ct, value, len);
380 set_bit(type, ct->head.set);
399 const enum nf_conntrack_attr type,
413 const enum nf_conntrack_attr type,
426 const enum nf_conntrack_attr type,
439 const enum nf_conntrack_attr type,
452 const enum nf_conntrack_attr type,
467 const enum nf_conntrack_attr type)
471 if (unlikely(type >= ATTR_MAX)) {
476 if (!test_bit(type, ct->head.set)) {
481 assert(get_attr_array[type]);
483 return get_attr_array[type](ct);
496 const enum nf_conntrack_attr type)
499 return ret == NULL ? 0 : *ret;
512 const enum nf_conntrack_attr type)
515 return ret == NULL ? 0 : *ret;
528 const enum nf_conntrack_attr type)
531 return ret == NULL ? 0 : *ret;
544 const enum nf_conntrack_attr type)
547 return ret == NULL ? 0 : *ret;
559 const enum nf_conntrack_attr type)
563 if (unlikely(type >= ATTR_MAX)) {
567 return test_bit(type, ct->head.set);
580 const enum nf_conntrack_attr *type_array,
587 for (i=0; i<size; i++) {
588 if (unlikely(type_array[i] >= ATTR_MAX)) {
592 if (!test_bit(type_array[i], ct->head.set))
607 const enum nf_conntrack_attr type)
611 if (unlikely(type >= ATTR_MAX)) {
615 unset_bit(type, ct->head.set);
630 const enum nf_conntrack_attr_grp type,
635 if (unlikely(type >= ATTR_GRP_MAX))
638 if (set_attr_grp_array[type]) {
639 set_attr_grp_array[type](ct, data);
640 set_bitmask_u32(ct->head.set,
641 attr_grp_bitmask[type].bitmask, __NFCT_BITSET);
655 const enum nf_conntrack_attr_grp type,
660 if (unlikely(type >= ATTR_GRP_MAX)) {
664 switch(attr_grp_bitmask[type].type) {
665 case NFCT_BITMASK_AND:
666 if (!test_bitmask_u32(ct->head.set,
667 attr_grp_bitmask[type].bitmask,
673 case NFCT_BITMASK_OR:
674 if (!test_bitmask_u32_or(ct->head.set,
675 attr_grp_bitmask[type].bitmask,
682 assert(get_attr_grp_array[type]);
683 get_attr_grp_array[type](ct, data);
695 const enum nf_conntrack_attr_grp type)
699 if (unlikely(type >= ATTR_GRP_MAX)) {
703 switch(attr_grp_bitmask[type].type) {
704 case NFCT_BITMASK_AND:
705 if (test_bitmask_u32(ct->head.set,
706 attr_grp_bitmask[type].bitmask,
711 case NFCT_BITMASK_OR:
712 if (test_bitmask_u32_or(ct->head.set,
713 attr_grp_bitmask[type].bitmask,
731 const enum nf_conntrack_attr_grp type)
735 if (unlikely(type >= ATTR_GRP_MAX)) {
739 unset_bitmask_u32(ct->head.set, attr_grp_bitmask[type].bitmask,
775 const struct nf_conntrack *ct)
781 return __build_conntrack(ssh, req, size, type, flags, ct);
785 __build_query_ct(
struct nfnl_subsys_handle *ssh,
786 const enum nf_conntrack_query qt,
787 const void *data,
void *buffer,
unsigned int size)
789 struct nfnlhdr *req = buffer;
790 const uint32_t *family = data;
793 assert(data != NULL);
796 memset(req, 0, size);
800 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
803 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK, data);
806 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
809 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_ACK, data);
812 nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK);
815 nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_DUMP);
817 case NFCT_Q_DUMP_RESET:
818 nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_REQUEST|NLM_F_DUMP);
820 case NFCT_Q_CREATE_UPDATE:
821 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data);
823 case NFCT_Q_DUMP_FILTER:
824 nfnl_fill_hdr(ssh, &req->nlh, 0, AF_UNSPEC, 0, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_DUMP);
825 __build_filter_dump(req, size, data);
827 case NFCT_Q_DUMP_FILTER_RESET:
828 nfnl_fill_hdr(ssh, &req->nlh, 0, AF_UNSPEC, 0, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_REQUEST|NLM_F_DUMP);
829 __build_filter_dump(req, size, data);
875 const enum nf_conntrack_query qt,
880 return __build_query_ct(ssh, qt, data, buffer, size);
908 const struct nlmsghdr *nlh,
909 struct nf_conntrack *ct)
912 int len = nlh->nlmsg_len;
913 struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
914 struct nfattr *cda[CTA_MAX];
919 len -= NLMSG_LENGTH(
sizeof(
struct nfgenmsg));
925 flags = __parse_message_type(nlh);
929 nfnl_parse_attr(cda, CTA_MAX, NFA_DATA(nfhdr), len);
931 __parse_conntrack(nlh, cda, ct);
955 const enum nf_conntrack_query qt,
958 const size_t size = 4096;
965 assert(data != NULL);
967 if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
970 return nfnl_query(h->nfnlh, &u.req.nlh);
987 const enum nf_conntrack_query qt,
990 const size_t size = 4096;
997 assert(data != NULL);
999 if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1002 return nfnl_send(h->nfnlh, &u.req.nlh);
1024 return nfnl_catch(h->nfnlh);
1078 const struct nf_conntrack *ct,
1079 unsigned int msg_type,
1080 unsigned int out_type,
1083 assert(buf != NULL);
1087 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, NULL);
1106 const struct nf_conntrack *ct,
1107 unsigned int msg_type,
1108 unsigned int out_type,
1112 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, map);
1130 const struct nf_conntrack *ct2)
1132 assert(ct1 != NULL);
1133 assert(ct2 != NULL);
1135 return __compare(ct1, ct2, NFCT_CMP_ALL);
1176 const struct nf_conntrack *ct2,
1179 assert(ct1 != NULL);
1180 assert(ct2 != NULL);
1182 return __compare(ct1, ct2, flags);
1211 const struct nf_conntrack *ct2,
1216 assert(ct1 != NULL);
1217 assert(ct2 != NULL);
1219 if (flags & NFCT_CP_OVERRIDE) {
1220 __copy_fast(ct1, ct2);
1223 if (flags == NFCT_CP_ALL) {
1224 for (i=0; i<ATTR_MAX; i++) {
1225 if (test_bit(i, ct2->head.set)) {
1226 assert(copy_attr_array[i]);
1227 copy_attr_array[i](ct1, ct2);
1228 set_bit(i, ct1->head.set);
1234 static const int cp_orig_mask[] = {
1247 #define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int)
1249 if (flags & NFCT_CP_ORIG) {
1250 for (i=0; i<__CP_ORIG_MAX; i++) {
1251 if (test_bit(cp_orig_mask[i], ct2->head.set)) {
1252 assert(copy_attr_array[i]);
1253 copy_attr_array[cp_orig_mask[i]](ct1, ct2);
1254 set_bit(cp_orig_mask[i], ct1->head.set);
1259 static const int cp_repl_mask[] = {
1269 #define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int)
1271 if (flags & NFCT_CP_REPL) {
1272 for (i=0; i<__CP_REPL_MAX; i++) {
1273 if (test_bit(cp_repl_mask[i], ct2->head.set)) {
1274 assert(copy_attr_array[i]);
1275 copy_attr_array[cp_repl_mask[i]](ct1, ct2);
1276 set_bit(cp_repl_mask[i], ct1->head.set);
1281 if (flags & NFCT_CP_META) {
1282 for (i=ATTR_TCP_STATE; i<ATTR_MAX; i++) {
1283 if (test_bit(i, ct2->head.set)) {
1284 assert(copy_attr_array[i]),
1285 copy_attr_array[i](ct1, ct2);
1286 set_bit(i, ct1->head.set);
1301 const struct nf_conntrack *ct2,
1302 const enum nf_conntrack_attr type)
1304 if (test_bit(type, ct2->head.set)) {
1305 assert(copy_attr_array[type]);
1306 copy_attr_array[type](ct1, ct2);
1307 set_bit(type, ct1->head.set);
1329 return calloc(
sizeof(
struct nfct_filter), 1);
1342 assert(filter != NULL);
1357 const enum nfct_filter_attr type,
1360 assert(filter != NULL);
1361 assert(value != NULL);
1363 if (unlikely(type >= NFCT_FILTER_MAX))
1366 if (filter_attr_array[type]) {
1367 filter_attr_array[type](filter, value);
1368 set_bit(type, filter->set);
1381 const enum nfct_filter_attr type,
1403 const enum nfct_filter_attr type,
1404 const enum nfct_filter_logic logic)
1406 if (unlikely(type >= NFCT_FILTER_MAX)) {
1411 if (filter->logic[type]) {
1416 filter->logic[type] = logic;
1432 assert(filter != NULL);
1434 return __setup_netlink_socket_filter(fd, filter);
1447 return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &val,
sizeof(val));
1468 return calloc(
sizeof(
struct nfct_filter_dump), 1);
1479 assert(filter != NULL);
1491 const enum nfct_filter_dump_attr type,
1494 assert(filter_dump != NULL);
1495 assert(value != NULL);
1497 if (unlikely(type >= NFCT_FILTER_DUMP_MAX))
1500 if (set_filter_dump_attr_array[type]) {
1501 set_filter_dump_attr_array[type](filter_dump, value);
1502 filter_dump->set |= (1 << type);
1513 const enum nfct_filter_dump_attr type,
1537 return __labels_get_path();
1552 return __labelmap_get_name(m, bit);
1565 return __labelmap_get_bit(m, name);
1578 return __labelmap_new(mapfile);
1590 __labelmap_destroy(map);
1611 struct nfct_bitmask *nfct_bitmask_new(
unsigned int max)
1613 struct nfct_bitmask *b;
1614 unsigned int bytes, words;
1619 words = DIV_ROUND_UP(max+1, 32);
1620 bytes = words *
sizeof(b->bits[0]);
1622 b = malloc(
sizeof(*b) + bytes);
1624 memset(b->bits, 0, bytes);
1637 struct nfct_bitmask *nfct_bitmask_clone(
const struct nfct_bitmask *b)
1639 unsigned int bytes = b->words *
sizeof(b->bits[0]);
1640 struct nfct_bitmask *copy;
1642 bytes +=
sizeof(*b);
1644 copy = malloc(bytes);
1646 memcpy(copy, b, bytes);
1656 void nfct_bitmask_set_bit(
struct nfct_bitmask *b,
unsigned int bit)
1658 unsigned int bits = b->words * 32;
1660 set_bit(bit, b->bits);
1671 int nfct_bitmask_test_bit(
const struct nfct_bitmask *b,
unsigned int bit)
1673 unsigned int bits = b->words * 32;
1674 return bit < bits && test_bit(bit, b->bits);
1683 void nfct_bitmask_unset_bit(
struct nfct_bitmask *b,
unsigned int bit)
1685 unsigned int bits = b->words * 32;
1687 unset_bit(bit, b->bits);
1695 unsigned int nfct_bitmask_maxbit(
const struct nfct_bitmask *b)
1697 return (b->words * 32) - 1;
1712 void nfct_bitmask_destroy(
struct nfct_bitmask *b)
1722 void nfct_bitmask_clear(
struct nfct_bitmask *b)
1724 unsigned int bytes = b->words *
sizeof(b->bits[0]);
1725 memset(b->bits, 0, bytes);
1737 bool nfct_bitmask_equal(
const struct nfct_bitmask *b1,
const struct nfct_bitmask *b2)
1739 if (b1->words != b2->words)
1742 return memcmp(b1->bits, b2->bits, b1->words *
sizeof(b1->bits[0])) == 0;
void nfct_filter_destroy(struct nfct_filter *filter)
void nfct_set_attr_l(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value, size_t len)
int nfct_send(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
uint16_t nfct_get_attr_u16(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
void nfct_set_attr_u64(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint64_t value)
void nfct_set_attr_u32(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint32_t value)
uint8_t nfct_get_attr_u8(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
const char * nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
void nfct_filter_add_attr_u32(struct nfct_filter *filter, const enum nfct_filter_attr type, uint32_t value)
int nfct_query(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
void nfct_set_attr(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value)
void nfct_copy_attr(struct nf_conntrack *ct1, const struct nf_conntrack *ct2, const enum nf_conntrack_attr type)
const char * nfct_labels_get_path(void)
void nfct_filter_dump_set_attr(struct nfct_filter_dump *filter_dump, const enum nfct_filter_dump_attr type, const void *value)
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)
void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump, const enum nfct_filter_dump_attr type, uint8_t value)
int nfct_get_attr_grp(const struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type, void *data)
void nfct_copy(struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags)
void nfct_destroy(struct nf_conntrack *ct)
int nfct_snprintf(char *buf, unsigned int size, const struct nf_conntrack *ct, unsigned int msg_type, unsigned int out_type, unsigned int flags)
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)
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_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)
struct nfct_labelmap * nfct_labelmap_new(const char *mapfile)
int nfct_setobjopt(struct nf_conntrack *ct, unsigned int option)
uint32_t nfct_get_attr_u32(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_parse_conntrack(enum nf_conntrack_msg_type type, const struct nlmsghdr *nlh, struct nf_conntrack *ct)
struct nf_conntrack * nfct_clone(const struct nf_conntrack *ct)
void nfct_callback_unregister(struct nfct_handle *h)
void nfct_callback_unregister2(struct nfct_handle *h)
int nfct_filter_set_logic(struct nfct_filter *filter, const enum nfct_filter_attr type, const enum nfct_filter_logic logic)
uint64_t nfct_get_attr_u64(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
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_set_attr_u16(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint16_t value)
struct nf_conntrack * nfct_new(void)
int nfct_build_query(struct nfnl_subsys_handle *ssh, const enum nf_conntrack_query qt, const void *data, void *buffer, unsigned int size)
int nfct_compare(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2)
int nfct_cmp(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags)
int nfct_filter_attach(int fd, struct nfct_filter *filter)
int nfct_getobjopt(const struct nf_conntrack *ct, unsigned int option)
int nfct_catch(struct nfct_handle *h)
int nfct_filter_detach(int fd)
void nfct_set_attr_u8(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint8_t value)
void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)
size_t nfct_sizeof(const struct nf_conntrack *ct)
int nfct_attr_grp_unset(struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type)
size_t nfct_maxsize(void)
int nfct_attr_is_set(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)
void nfct_labelmap_destroy(struct nfct_labelmap *map)
int nfct_attr_unset(struct nf_conntrack *ct, const enum nf_conntrack_attr type)
struct nfct_filter_dump * nfct_filter_dump_create(void)
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)