libnetfilter_conntrack 1.1.0
conntrack/api.c
1/*
2 * (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include <stdlib.h>
11#include <stdbool.h>
12#include <string.h> /* for memset */
13#include <errno.h>
14#include <assert.h>
15#include <libmnl/libmnl.h>
16
17#include "internal/internal.h"
18
76struct nf_conntrack *nfct_new(void)
77{
78 struct nf_conntrack *ct;
79
80 ct = malloc(sizeof(struct nf_conntrack));
81 if (!ct)
82 return NULL;
83
84 memset(ct, 0, sizeof(struct nf_conntrack));
85
86 return ct;
87}
88
93void nfct_destroy(struct nf_conntrack *ct)
94{
95 assert(ct != NULL);
96 if (ct->secctx)
97 free(ct->secctx);
98 if (ct->helper_info)
99 free(ct->helper_info);
100 if (ct->connlabels)
101 nfct_bitmask_destroy(ct->connlabels);
102 if (ct->connlabels_mask)
103 nfct_bitmask_destroy(ct->connlabels_mask);
104 free(ct);
105 ct = NULL; /* bugtrap */
106}
107
114size_t nfct_sizeof(const struct nf_conntrack *ct)
115{
116 assert(ct != NULL);
117 return sizeof(*ct);
118}
119
136size_t nfct_maxsize(void)
137{
138 return sizeof(struct nf_conntrack);
139}
140
148struct nf_conntrack *nfct_clone(const struct nf_conntrack *ct)
149{
150 struct nf_conntrack *clone;
151
152 assert(ct != NULL);
153
154 if ((clone = nfct_new()) == NULL)
155 return NULL;
156 nfct_copy(clone, ct, NFCT_CP_OVERRIDE);
157
158 return clone;
159}
160
169int nfct_setobjopt(struct nf_conntrack *ct, unsigned int option)
170{
171 assert(ct != NULL);
172
173 if (unlikely(option > NFCT_SOPT_MAX)) {
174 errno = EOPNOTSUPP;
175 return -1;
176 }
177
178 return __setobjopt(ct, option);
179}
180
189int nfct_getobjopt(const struct nf_conntrack *ct, unsigned int option)
190{
191 assert(ct != NULL);
192
193 if (unlikely(option > NFCT_GOPT_MAX)) {
194 errno = EOPNOTSUPP;
195 return -1;
196 }
197
198 return __getobjopt(ct, option);
199}
200
224int nfct_callback_register(struct nfct_handle *h,
225 enum nf_conntrack_msg_type type,
226 int (*cb)(enum nf_conntrack_msg_type type,
227 struct nf_conntrack *ct,
228 void *data),
229 void *data)
230{
231 struct __data_container *container;
232
233 assert(h != NULL);
234
235 container = malloc(sizeof(struct __data_container));
236 if (!container)
237 return -1;
238 memset(container, 0, sizeof(struct __data_container));
239
240 h->cb = cb;
241 container->h = h;
242 container->type = type;
243 container->data = data;
244
245 h->nfnl_cb_ct.call = __callback;
246 h->nfnl_cb_ct.data = container;
247 h->nfnl_cb_ct.attr_count = CTA_MAX;
248
249 nfnl_callback_register(h->nfnlssh_ct,
250 IPCTNL_MSG_CT_NEW,
251 &h->nfnl_cb_ct);
252
253 nfnl_callback_register(h->nfnlssh_ct,
254 IPCTNL_MSG_CT_DELETE,
255 &h->nfnl_cb_ct);
256
257 return 0;
258}
259
264void nfct_callback_unregister(struct nfct_handle *h)
265{
266 assert(h != NULL);
267
268 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
269 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
270
271 h->cb = NULL;
272 free(h->nfnl_cb_ct.data);
273
274 h->nfnl_cb_ct.call = NULL;
275 h->nfnl_cb_ct.data = NULL;
276 h->nfnl_cb_ct.attr_count = 0;
277}
278
298int nfct_callback_register2(struct nfct_handle *h,
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,
303 void *data),
304 void *data)
305{
306 struct __data_container *container;
307
308 assert(h != NULL);
309
310 container = calloc(1, sizeof(struct __data_container));
311 if (container == NULL)
312 return -1;
313
314 h->cb2 = cb;
315 container->h = h;
316 container->type = type;
317 container->data = data;
318
319 h->nfnl_cb_ct.call = __callback;
320 h->nfnl_cb_ct.data = container;
321 h->nfnl_cb_ct.attr_count = CTA_MAX;
322
323 nfnl_callback_register(h->nfnlssh_ct,
324 IPCTNL_MSG_CT_NEW,
325 &h->nfnl_cb_ct);
326
327 nfnl_callback_register(h->nfnlssh_ct,
328 IPCTNL_MSG_CT_DELETE,
329 &h->nfnl_cb_ct);
330
331 return 0;
332}
333
338void nfct_callback_unregister2(struct nfct_handle *h)
339{
340 assert(h != NULL);
341
342 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
343 nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
344
345 h->cb2 = NULL;
346 free(h->nfnl_cb_ct.data);
347
348 h->nfnl_cb_ct.call = NULL;
349 h->nfnl_cb_ct.data = NULL;
350 h->nfnl_cb_ct.attr_count = 0;
351}
352
369void
370nfct_set_attr_l(struct nf_conntrack *ct, const enum nf_conntrack_attr type,
371 const void *value, size_t len)
372{
373 assert(ct != NULL);
374 assert(value != NULL);
375
376 if (unlikely(type >= ATTR_MAX))
377 return;
378
379 if (set_attr_array[type]) {
380 set_attr_array[type](ct, value, len);
381 set_bit(type, ct->head.set);
382 }
383}
384
399void nfct_set_attr(struct nf_conntrack *ct,
400 const enum nf_conntrack_attr type,
401 const void *value)
402{
403 /* We assume the setter knows the size of the passed pointer. */
404 nfct_set_attr_l(ct, type, value, 0);
405}
406
413void nfct_set_attr_u8(struct nf_conntrack *ct,
414 const enum nf_conntrack_attr type,
415 uint8_t value)
416{
417 nfct_set_attr_l(ct, type, &value, sizeof(uint8_t));
418}
419
426void nfct_set_attr_u16(struct nf_conntrack *ct,
427 const enum nf_conntrack_attr type,
428 uint16_t value)
429{
430 nfct_set_attr_l(ct, type, &value, sizeof(uint16_t));
431}
432
439void nfct_set_attr_u32(struct nf_conntrack *ct,
440 const enum nf_conntrack_attr type,
441 uint32_t value)
442{
443 nfct_set_attr_l(ct, type, &value, sizeof(uint32_t));
444}
445
452void nfct_set_attr_u64(struct nf_conntrack *ct,
453 const enum nf_conntrack_attr type,
454 uint64_t value)
455{
456 nfct_set_attr_l(ct, type, &value, sizeof(uint64_t));
457}
458
467const void *nfct_get_attr(const struct nf_conntrack *ct,
468 const enum nf_conntrack_attr type)
469{
470 assert(ct != NULL);
471
472 if (unlikely(type >= ATTR_MAX)) {
473 errno = EINVAL;
474 return NULL;
475 }
476
477 if (!test_bit(type, ct->head.set)) {
478 errno = ENODATA;
479 return NULL;
480 }
481
482 assert(get_attr_array[type]);
483
484 return get_attr_array[type](ct);
485}
486
496uint8_t nfct_get_attr_u8(const struct nf_conntrack *ct,
497 const enum nf_conntrack_attr type)
498{
499 const uint8_t *ret = nfct_get_attr(ct, type);
500 return ret == NULL ? 0 : *ret;
501}
502
512uint16_t nfct_get_attr_u16(const struct nf_conntrack *ct,
513 const enum nf_conntrack_attr type)
514{
515 const uint16_t *ret = nfct_get_attr(ct, type);
516 return ret == NULL ? 0 : *ret;
517}
518
528uint32_t nfct_get_attr_u32(const struct nf_conntrack *ct,
529 const enum nf_conntrack_attr type)
530{
531 const uint32_t *ret = nfct_get_attr(ct, type);
532 return ret == NULL ? 0 : *ret;
533}
534
544uint64_t nfct_get_attr_u64(const struct nf_conntrack *ct,
545 const enum nf_conntrack_attr type)
546{
547 const uint64_t *ret = nfct_get_attr(ct, type);
548 return ret == NULL ? 0 : *ret;
549}
550
559int nfct_attr_is_set(const struct nf_conntrack *ct,
560 const enum nf_conntrack_attr type)
561{
562 assert(ct != NULL);
563
564 if (unlikely(type >= ATTR_MAX)) {
565 errno = EINVAL;
566 return -1;
567 }
568 return test_bit(type, ct->head.set);
569}
570
580int nfct_attr_is_set_array(const struct nf_conntrack *ct,
581 const enum nf_conntrack_attr *type_array,
582 int size)
583{
584 int i;
585
586 assert(ct != NULL);
587
588 for (i=0; i<size; i++) {
589 if (unlikely(type_array[i] >= ATTR_MAX)) {
590 errno = EINVAL;
591 return -1;
592 }
593 if (!test_bit(type_array[i], ct->head.set))
594 return 0;
595 }
596 return 1;
597}
598
607int nfct_attr_unset(struct nf_conntrack *ct,
608 const enum nf_conntrack_attr type)
609{
610 assert(ct != NULL);
611
612 if (unlikely(type >= ATTR_MAX)) {
613 errno = EINVAL;
614 return -1;
615 }
616 unset_bit(type, ct->head.set);
617
618 return 0;
619}
620
630void nfct_set_attr_grp(struct nf_conntrack *ct,
631 const enum nf_conntrack_attr_grp type,
632 const void *data)
633{
634 assert(ct != NULL);
635
636 if (unlikely(type >= ATTR_GRP_MAX))
637 return;
638
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);
643 }
644}
645
655int nfct_get_attr_grp(const struct nf_conntrack *ct,
656 const enum nf_conntrack_attr_grp type,
657 void *data)
658{
659 assert(ct != NULL);
660
661 if (unlikely(type >= ATTR_GRP_MAX)) {
662 errno = EINVAL;
663 return -1;
664 }
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,
669 __NFCT_BITSET)) {
670 errno = ENODATA;
671 return -1;
672 }
673 break;
674 case NFCT_BITMASK_OR:
675 if (!test_bitmask_u32_or(ct->head.set,
676 attr_grp_bitmask[type].bitmask,
677 __NFCT_BITSET)) {
678 errno = ENODATA;
679 return -1;
680 }
681 break;
682 }
683 assert(get_attr_grp_array[type]);
684 get_attr_grp_array[type](ct, data);
685 return 0;
686}
687
695int nfct_attr_grp_is_set(const struct nf_conntrack *ct,
696 const enum nf_conntrack_attr_grp type)
697{
698 assert(ct != NULL);
699
700 if (unlikely(type >= ATTR_GRP_MAX)) {
701 errno = EINVAL;
702 return -1;
703 }
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,
708 __NFCT_BITSET)) {
709 return 1;
710 }
711 break;
712 case NFCT_BITMASK_OR:
713 if (test_bitmask_u32_or(ct->head.set,
714 attr_grp_bitmask[type].bitmask,
715 __NFCT_BITSET)) {
716 return 1;
717 }
718 break;
719 }
720 return 0;
721}
722
731int nfct_attr_grp_unset(struct nf_conntrack *ct,
732 const enum nf_conntrack_attr_grp type)
733{
734 assert(ct != NULL);
735
736 if (unlikely(type >= ATTR_GRP_MAX)) {
737 errno = EINVAL;
738 return -1;
739 }
740 unset_bitmask_u32(ct->head.set, attr_grp_bitmask[type].bitmask,
741 __NFCT_BITSET);
742
743 return 0;
744}
745
771int nfct_build_conntrack(struct nfnl_subsys_handle *ssh,
772 void *req,
773 size_t size,
774 uint16_t type,
775 uint16_t flags,
776 const struct nf_conntrack *ct)
777{
778 assert(ssh != NULL);
779 assert(req != NULL);
780 assert(ct != NULL);
781
782 memset(req, 0, size);
783
784 return __build_conntrack(req, size, type, flags, ct);
785}
786
787static void nfct_fill_hdr(struct nfnlhdr *req, uint16_t type, uint16_t flags,
788 uint8_t l3num, uint8_t version)
789{
790 char *buf = (char *)&req->nlh;
791 struct nlmsghdr *nlh;
792 struct nfgenmsg *nfh;
793
794 nlh = mnl_nlmsg_put_header(buf);
795 nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | type;
796 nlh->nlmsg_flags = NLM_F_REQUEST | flags;
797 nlh->nlmsg_seq = 0;
798
799 nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
800 nfh->nfgen_family = l3num;
801 nfh->version = version;
802 nfh->res_id = 0;
803}
804
805static int
806__build_query_ct(const enum nf_conntrack_query qt,
807 const void *data, void *buffer, unsigned int size)
808{
809 struct nfnlhdr *req = buffer;
810 const uint32_t *family = data;
811
812 assert(data != NULL);
813 assert(req != NULL);
814
815 memset(buffer, 0, size);
816
817 switch(qt) {
818 case NFCT_Q_CREATE:
819 __build_conntrack(req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
820 break;
821 case NFCT_Q_UPDATE:
822 __build_conntrack(req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK, data);
823 break;
824 case NFCT_Q_DESTROY:
825 __build_conntrack(req, size, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
826 break;
827 case NFCT_Q_GET:
828 __build_conntrack(req, size, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_ACK, data);
829 break;
830 case NFCT_Q_FLUSH:
831 nfct_fill_hdr(req, IPCTNL_MSG_CT_DELETE, NLM_F_ACK, *family,
832 NFNETLINK_V0);
833 break;
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)
837 return -1;
838 break;
839 case NFCT_Q_DUMP:
840 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, *family,
841 NFNETLINK_V0);
842 break;
843 case NFCT_Q_DUMP_RESET:
844 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
845 *family, NFNETLINK_V0);
846 break;
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);
849 break;
850 case NFCT_Q_DUMP_FILTER:
851 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, AF_UNSPEC,
852 NFNETLINK_V0);
853 if (__build_filter_dump(req, size, data) < 0)
854 return -1;
855 break;
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)
860 return -1;
861 break;
862 default:
863 errno = ENOTSUP;
864 return -1;
865 }
866 return 1;
867}
868
905int nfct_build_query(struct nfnl_subsys_handle *ssh,
906 const enum nf_conntrack_query qt,
907 const void *data,
908 void *buffer,
909 unsigned int size)
910{
911 return __build_query_ct(qt, data, buffer, size);
912}
913
914static int __parse_message_type(const struct nlmsghdr *nlh)
915{
916 uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
917 uint16_t flags = nlh->nlmsg_flags;
918 int ret = NFCT_T_UNKNOWN;
919
920 if (type == IPCTNL_MSG_CT_NEW) {
921 if (flags & (NLM_F_CREATE|NLM_F_EXCL))
922 ret = NFCT_T_NEW;
923 else
924 ret = NFCT_T_UPDATE;
925 } else if (type == IPCTNL_MSG_CT_DELETE)
926 ret = NFCT_T_DESTROY;
927
928 return ret;
929}
930
955int nfct_parse_conntrack(enum nf_conntrack_msg_type type,
956 const struct nlmsghdr *nlh,
957 struct nf_conntrack *ct)
958{
959 unsigned int flags;
960
961 assert(nlh != NULL);
962 assert(ct != NULL);
963
964 flags = __parse_message_type(nlh);
965 if (!(flags & type))
966 return 0;
967
968 nfct_nlmsg_parse(nlh, ct);
969
970 return flags;
971}
972
991int nfct_query(struct nfct_handle *h,
992 const enum nf_conntrack_query qt,
993 const void *data)
994{
995 const size_t size = 4096; /* enough for now */
996 union {
997 char buffer[size];
998 struct nfnlhdr req;
999 } u;
1000
1001 assert(h != NULL);
1002 assert(data != NULL);
1003
1004 if (__build_query_ct(qt, data, &u.req, size) == -1)
1005 return -1;
1006
1007 return nfnl_query(h->nfnlh, &u.req.nlh);
1008}
1009
1023int nfct_send(struct nfct_handle *h,
1024 const enum nf_conntrack_query qt,
1025 const void *data)
1026{
1027 const size_t size = 4096; /* enough for now */
1028 union {
1029 char buffer[size];
1030 struct nfnlhdr req;
1031 } u;
1032
1033 assert(h != NULL);
1034 assert(data != NULL);
1035
1036 if (__build_query_ct(qt, data, &u.req, size) == -1)
1037 return -1;
1038
1039 return nfnl_send(h->nfnlh, &u.req.nlh);
1040}
1041
1042
1057int nfct_catch(struct nfct_handle *h)
1058{
1059 assert(h != NULL);
1060
1061 return nfnl_catch(h->nfnlh);
1062}
1063
1113int nfct_snprintf(char *buf,
1114 unsigned int size,
1115 const struct nf_conntrack *ct,
1116 unsigned int msg_type,
1117 unsigned int out_type,
1118 unsigned int flags)
1119{
1120 assert(buf != NULL);
1121 assert(size > 0);
1122 assert(ct != NULL);
1123
1124 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, NULL);
1125}
1126
1142 unsigned int size,
1143 const struct nf_conntrack *ct,
1144 unsigned int msg_type,
1145 unsigned int out_type,
1146 unsigned int flags,
1147 struct nfct_labelmap *map)
1148{
1149 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, map);
1150}
1151
1166int nfct_compare(const struct nf_conntrack *ct1,
1167 const struct nf_conntrack *ct2)
1168{
1169 assert(ct1 != NULL);
1170 assert(ct2 != NULL);
1171
1172 return __compare(ct1, ct2, NFCT_CMP_ALL);
1173}
1174
1212int nfct_cmp(const struct nf_conntrack *ct1,
1213 const struct nf_conntrack *ct2,
1214 unsigned int flags)
1215{
1216 assert(ct1 != NULL);
1217 assert(ct2 != NULL);
1218
1219 return __compare(ct1, ct2, flags);
1220}
1221
1247void nfct_copy(struct nf_conntrack *ct1,
1248 const struct nf_conntrack *ct2,
1249 unsigned int flags)
1250{
1251 int i;
1252
1253 assert(ct1 != NULL);
1254 assert(ct2 != NULL);
1255
1256 if (flags & NFCT_CP_OVERRIDE) {
1257 __copy_fast(ct1, ct2);
1258 return;
1259 }
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);
1266 }
1267 }
1268 return;
1269 }
1270
1271 static const int cp_orig_mask[] = {
1272 ATTR_ORIG_IPV4_SRC,
1273 ATTR_ORIG_IPV4_DST,
1274 ATTR_ORIG_IPV6_SRC,
1275 ATTR_ORIG_IPV6_DST,
1276 ATTR_ORIG_PORT_SRC,
1277 ATTR_ORIG_PORT_DST,
1278 ATTR_ICMP_TYPE,
1279 ATTR_ICMP_CODE,
1280 ATTR_ICMP_ID,
1281 ATTR_ORIG_L3PROTO,
1282 ATTR_ORIG_L4PROTO,
1283 };
1284 #define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int)
1285
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);
1292 }
1293 }
1294 }
1295
1296 static const int cp_repl_mask[] = {
1297 ATTR_REPL_IPV4_SRC,
1298 ATTR_REPL_IPV4_DST,
1299 ATTR_REPL_IPV6_SRC,
1300 ATTR_REPL_IPV6_DST,
1301 ATTR_REPL_PORT_SRC,
1302 ATTR_REPL_PORT_DST,
1303 ATTR_REPL_L3PROTO,
1304 ATTR_REPL_L4PROTO,
1305 };
1306 #define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int)
1307
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);
1314 }
1315 }
1316 }
1317
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);
1324 }
1325 }
1326 }
1327}
1328
1337void nfct_copy_attr(struct nf_conntrack *ct1,
1338 const struct nf_conntrack *ct2,
1339 const enum nf_conntrack_attr type)
1340{
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);
1345 }
1346}
1347
1364struct nfct_filter *nfct_filter_create(void)
1365{
1366 return calloc(1, sizeof(struct nfct_filter));
1367}
1368
1377void nfct_filter_destroy(struct nfct_filter *filter)
1378{
1379 assert(filter != NULL);
1380 free(filter);
1381 filter = NULL;
1382}
1383
1393void nfct_filter_add_attr(struct nfct_filter *filter,
1394 const enum nfct_filter_attr type,
1395 const void *value)
1396{
1397 assert(filter != NULL);
1398 assert(value != NULL);
1399
1400 if (unlikely(type >= NFCT_FILTER_MAX))
1401 return;
1402
1403 if (filter_attr_array[type]) {
1404 filter_attr_array[type](filter, value);
1405 set_bit(type, filter->set);
1406 }
1407}
1408
1417void nfct_filter_add_attr_u32(struct nfct_filter *filter,
1418 const enum nfct_filter_attr type,
1419 uint32_t value)
1420{
1421 nfct_filter_add_attr(filter, type, &value);
1422}
1423
1439int nfct_filter_set_logic(struct nfct_filter *filter,
1440 const enum nfct_filter_attr type,
1441 const enum nfct_filter_logic logic)
1442{
1443 if (unlikely(type >= NFCT_FILTER_MAX)) {
1444 errno = ENOTSUP;
1445 return -1;
1446 }
1447
1448 if (filter->logic[type]) {
1449 errno = EBUSY;
1450 return -1;
1451 }
1452
1453 filter->logic[type] = logic;
1454
1455 return 0;
1456}
1457
1467int nfct_filter_attach(int fd, struct nfct_filter *filter)
1468{
1469 assert(filter != NULL);
1470
1471 return __setup_netlink_socket_filter(fd, filter);
1472}
1473
1481{
1482 int val = 0;
1483
1484 return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val));
1485}
1486
1503struct nfct_filter_dump *nfct_filter_dump_create(void)
1504{
1505 return calloc(1, sizeof(struct nfct_filter_dump));
1506}
1507
1514void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
1515{
1516 assert(filter != NULL);
1517 free(filter);
1518 filter = NULL;
1519}
1520
1527void nfct_filter_dump_set_attr(struct nfct_filter_dump *filter_dump,
1528 const enum nfct_filter_dump_attr type,
1529 const void *value)
1530{
1531 assert(filter_dump != NULL);
1532 assert(value != NULL);
1533
1534 if (unlikely(type >= NFCT_FILTER_DUMP_MAX))
1535 return;
1536
1537 if (set_filter_dump_attr_array[type]) {
1538 set_filter_dump_attr_array[type](filter_dump, value);
1539 filter_dump->set |= (1 << type);
1540 }
1541}
1542
1549void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump,
1550 const enum nfct_filter_dump_attr type,
1551 uint8_t value)
1552{
1553 nfct_filter_dump_set_attr(filter_dump, type, &value);
1554}
1555
1562void nfct_filter_dump_set_attr_u16(struct nfct_filter_dump *filter_dump,
1563 const enum nfct_filter_dump_attr type,
1564 uint16_t value)
1565{
1566 nfct_filter_dump_set_attr(filter_dump, type, &value);
1567}
1568
1585const char *nfct_labels_get_path(void)
1586{
1587 return __labels_get_path();
1588}
1589
1600const char *nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
1601{
1602 return __labelmap_get_name(m, bit);
1603}
1604
1613int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)
1614{
1615 return __labelmap_get_bit(m, name);
1616}
1617
1626struct nfct_labelmap *nfct_labelmap_new(const char *mapfile)
1627{
1628 return __labelmap_new(mapfile);
1629}
1630
1639{
1640 __labelmap_destroy(map);
1641}
1642
1647/*
1648 * \defgroup bitmask bitmask object
1649 *
1650 * @{
1651 */
1652
1661struct nfct_bitmask *nfct_bitmask_new(unsigned int max)
1662{
1663 struct nfct_bitmask *b;
1664 unsigned int bytes, words;
1665
1666 if (max > 0xffff)
1667 return NULL;
1668
1669 words = DIV_ROUND_UP(max+1, 32);
1670 bytes = words * sizeof(b->bits[0]);
1671
1672 b = malloc(sizeof(*b) + bytes);
1673 if (b) {
1674 memset(b->bits, 0, bytes);
1675 b->words = words;
1676 }
1677 return b;
1678}
1679
1680/*
1681 * nfct_bitmask_clone - duplicate a bitmask object
1682 *
1683 * \param b pointer to the bitmask object to duplicate
1684 *
1685 * returns an identical copy of the bitmask.
1686 */
1687struct nfct_bitmask *nfct_bitmask_clone(const struct nfct_bitmask *b)
1688{
1689 unsigned int bytes = b->words * sizeof(b->bits[0]);
1690 struct nfct_bitmask *copy;
1691
1692 bytes += sizeof(*b);
1693
1694 copy = malloc(bytes);
1695 if (copy)
1696 memcpy(copy, b, bytes);
1697 return copy;
1698}
1699
1700/*
1701 * nfct_bitmask_set_bit - set bit in the bitmask
1702 *
1703 * \param b pointer to the bitmask object
1704 * \param bit the bit to set
1705 */
1706void nfct_bitmask_set_bit(struct nfct_bitmask *b, unsigned int bit)
1707{
1708 unsigned int bits = b->words * 32;
1709 if (bit < bits)
1710 set_bit(bit, b->bits);
1711}
1712
1713/*
1714 * nfct_bitmask_test_bit - test if a bit in the bitmask is set
1715 *
1716 * \param b pointer to the bitmask object
1717 * \param bit the bit to test
1718 *
1719 * returns 0 if the bit is not set.
1720 */
1721int nfct_bitmask_test_bit(const struct nfct_bitmask *b, unsigned int bit)
1722{
1723 unsigned int bits = b->words * 32;
1724 return bit < bits && test_bit(bit, b->bits);
1725}
1726
1727/*
1728 * nfct_bitmask_unset_bit - unset bit in the bitmask
1729 *
1730 * \param b pointer to the bitmask object
1731 * \param bit the bit to clear
1732 */
1733void nfct_bitmask_unset_bit(struct nfct_bitmask *b, unsigned int bit)
1734{
1735 unsigned int bits = b->words * 32;
1736 if (bit < bits)
1737 unset_bit(bit, b->bits);
1738}
1739
1740/*
1741 * nfct_bitmask_maxbit - return highest bit that may be set/unset
1742 *
1743 * \param b pointer to the bitmask object
1744 */
1745unsigned int nfct_bitmask_maxbit(const struct nfct_bitmask *b)
1746{
1747 return (b->words * 32) - 1;
1748}
1749
1750/*
1751 * nfct_bitmask_destroy - destroy bitmask object
1752 *
1753 * \param b pointer to the bitmask object
1754 *
1755 * This function releases the memory that is used by the bitmask object.
1756 *
1757 * If you assign a bitmask object to a nf_conntrack object using
1758 * nfct_set_attr ATTR_CONNLABEL, then the ownership of the bitmask
1759 * object passes on to the nf_conntrack object. The nfct_bitmask object
1760 * will be destroyed when the nf_conntrack object is destroyed.
1761 */
1762void nfct_bitmask_destroy(struct nfct_bitmask *b)
1763{
1764 free(b);
1765}
1766
1767/*
1768 * nfct_bitmask_clear - clear a bitmask object
1769 *
1770 * \param b pointer to the bitmask object to clear
1771 */
1772void nfct_bitmask_clear(struct nfct_bitmask *b)
1773{
1774 unsigned int bytes = b->words * sizeof(b->bits[0]);
1775 memset(b->bits, 0, bytes);
1776}
1777
1778/*
1779 * nfct_bitmask_equal - compare two bitmask objects
1780 *
1781 * \param b1 pointer to a valid bitmask object
1782 * \param b2 pointer to a valid bitmask object
1783 *
1784 * If both bitmask object are equal, this function returns true, otherwise
1785 * false is returned.
1786 */
1787bool nfct_bitmask_equal(const struct nfct_bitmask *b1, const struct nfct_bitmask *b2)
1788{
1789 if (b1->words != b2->words)
1790 return false;
1791
1792 return memcmp(b1->bits, b2->bits, b1->words * sizeof(b1->bits[0])) == 0;
1793}
1794
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)