libnetfilter_conntrack 1.0.9
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(sizeof(struct __data_container), 1);
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 return __build_conntrack(ssh, req, size, type, flags, ct);
783}
784
785static void nfct_fill_hdr(struct nfnlhdr *req, uint16_t type, uint16_t flags,
786 uint8_t l3num, uint8_t version)
787{
788 char *buf = (char *)&req->nlh;
789 struct nlmsghdr *nlh;
790 struct nfgenmsg *nfh;
791
792 nlh = mnl_nlmsg_put_header(buf);
793 nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | type;
794 nlh->nlmsg_flags = NLM_F_REQUEST | flags;
795 nlh->nlmsg_seq = 0;
796
797 nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
798 nfh->nfgen_family = l3num;
799 nfh->version = version;
800 nfh->res_id = 0;
801}
802
803static int
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)
807{
808 struct nfnlhdr *req = buffer;
809 const uint32_t *family = data;
810
811 assert(ssh != NULL);
812 assert(data != NULL);
813 assert(req != NULL);
814
815 memset(req, 0, size);
816
817 switch(qt) {
818 case NFCT_Q_CREATE:
819 __build_conntrack(ssh, 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(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK, data);
823 break;
824 case NFCT_Q_DESTROY:
825 __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
826 break;
827 case NFCT_Q_GET:
828 __build_conntrack(ssh, 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 break;
837 case NFCT_Q_DUMP:
838 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, *family,
839 NFNETLINK_V0);
840 break;
841 case NFCT_Q_DUMP_RESET:
842 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
843 *family, NFNETLINK_V0);
844 break;
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);
847 break;
848 case NFCT_Q_DUMP_FILTER:
849 nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, AF_UNSPEC,
850 NFNETLINK_V0);
851 __build_filter_dump(req, size, data);
852 break;
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);
857 break;
858 default:
859 errno = ENOTSUP;
860 return -1;
861 }
862 return 1;
863}
864
901int nfct_build_query(struct nfnl_subsys_handle *ssh,
902 const enum nf_conntrack_query qt,
903 const void *data,
904 void *buffer,
905 unsigned int size)
906{
907 return __build_query_ct(ssh, qt, data, buffer, size);
908}
909
910static int __parse_message_type(const struct nlmsghdr *nlh)
911{
912 uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
913 uint16_t flags = nlh->nlmsg_flags;
914 int ret = NFCT_T_UNKNOWN;
915
916 if (type == IPCTNL_MSG_CT_NEW) {
917 if (flags & (NLM_F_CREATE|NLM_F_EXCL))
918 ret = NFCT_T_NEW;
919 else
920 ret = NFCT_T_UPDATE;
921 } else if (type == IPCTNL_MSG_CT_DELETE)
922 ret = NFCT_T_DESTROY;
923
924 return ret;
925}
926
951int nfct_parse_conntrack(enum nf_conntrack_msg_type type,
952 const struct nlmsghdr *nlh,
953 struct nf_conntrack *ct)
954{
955 unsigned int flags;
956
957 assert(nlh != NULL);
958 assert(ct != NULL);
959
960 flags = __parse_message_type(nlh);
961 if (!(flags & type))
962 return 0;
963
964 nfct_nlmsg_parse(nlh, ct);
965
966 return flags;
967}
968
987int nfct_query(struct nfct_handle *h,
988 const enum nf_conntrack_query qt,
989 const void *data)
990{
991 const size_t size = 4096; /* enough for now */
992 union {
993 char buffer[size];
994 struct nfnlhdr req;
995 } u;
996
997 assert(h != NULL);
998 assert(data != NULL);
999
1000 if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1001 return -1;
1002
1003 return nfnl_query(h->nfnlh, &u.req.nlh);
1004}
1005
1019int nfct_send(struct nfct_handle *h,
1020 const enum nf_conntrack_query qt,
1021 const void *data)
1022{
1023 const size_t size = 4096; /* enough for now */
1024 union {
1025 char buffer[size];
1026 struct nfnlhdr req;
1027 } u;
1028
1029 assert(h != NULL);
1030 assert(data != NULL);
1031
1032 if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1033 return -1;
1034
1035 return nfnl_send(h->nfnlh, &u.req.nlh);
1036}
1037
1038
1053int nfct_catch(struct nfct_handle *h)
1054{
1055 assert(h != NULL);
1056
1057 return nfnl_catch(h->nfnlh);
1058}
1059
1109int nfct_snprintf(char *buf,
1110 unsigned int size,
1111 const struct nf_conntrack *ct,
1112 unsigned int msg_type,
1113 unsigned int out_type,
1114 unsigned int flags)
1115{
1116 assert(buf != NULL);
1117 assert(size > 0);
1118 assert(ct != NULL);
1119
1120 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, NULL);
1121}
1122
1138 unsigned int size,
1139 const struct nf_conntrack *ct,
1140 unsigned int msg_type,
1141 unsigned int out_type,
1142 unsigned int flags,
1143 struct nfct_labelmap *map)
1144{
1145 return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, map);
1146}
1147
1162int nfct_compare(const struct nf_conntrack *ct1,
1163 const struct nf_conntrack *ct2)
1164{
1165 assert(ct1 != NULL);
1166 assert(ct2 != NULL);
1167
1168 return __compare(ct1, ct2, NFCT_CMP_ALL);
1169}
1170
1208int nfct_cmp(const struct nf_conntrack *ct1,
1209 const struct nf_conntrack *ct2,
1210 unsigned int flags)
1211{
1212 assert(ct1 != NULL);
1213 assert(ct2 != NULL);
1214
1215 return __compare(ct1, ct2, flags);
1216}
1217
1243void nfct_copy(struct nf_conntrack *ct1,
1244 const struct nf_conntrack *ct2,
1245 unsigned int flags)
1246{
1247 int i;
1248
1249 assert(ct1 != NULL);
1250 assert(ct2 != NULL);
1251
1252 if (flags & NFCT_CP_OVERRIDE) {
1253 __copy_fast(ct1, ct2);
1254 return;
1255 }
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);
1262 }
1263 }
1264 return;
1265 }
1266
1267 static const int cp_orig_mask[] = {
1268 ATTR_ORIG_IPV4_SRC,
1269 ATTR_ORIG_IPV4_DST,
1270 ATTR_ORIG_IPV6_SRC,
1271 ATTR_ORIG_IPV6_DST,
1272 ATTR_ORIG_PORT_SRC,
1273 ATTR_ORIG_PORT_DST,
1274 ATTR_ICMP_TYPE,
1275 ATTR_ICMP_CODE,
1276 ATTR_ICMP_ID,
1277 ATTR_ORIG_L3PROTO,
1278 ATTR_ORIG_L4PROTO,
1279 };
1280 #define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int)
1281
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);
1288 }
1289 }
1290 }
1291
1292 static const int cp_repl_mask[] = {
1293 ATTR_REPL_IPV4_SRC,
1294 ATTR_REPL_IPV4_DST,
1295 ATTR_REPL_IPV6_SRC,
1296 ATTR_REPL_IPV6_DST,
1297 ATTR_REPL_PORT_SRC,
1298 ATTR_REPL_PORT_DST,
1299 ATTR_REPL_L3PROTO,
1300 ATTR_REPL_L4PROTO,
1301 };
1302 #define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int)
1303
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);
1310 }
1311 }
1312 }
1313
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);
1320 }
1321 }
1322 }
1323}
1324
1333void nfct_copy_attr(struct nf_conntrack *ct1,
1334 const struct nf_conntrack *ct2,
1335 const enum nf_conntrack_attr type)
1336{
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);
1341 }
1342}
1343
1360struct nfct_filter *nfct_filter_create(void)
1361{
1362 return calloc(sizeof(struct nfct_filter), 1);
1363}
1364
1373void nfct_filter_destroy(struct nfct_filter *filter)
1374{
1375 assert(filter != NULL);
1376 free(filter);
1377 filter = NULL;
1378}
1379
1389void nfct_filter_add_attr(struct nfct_filter *filter,
1390 const enum nfct_filter_attr type,
1391 const void *value)
1392{
1393 assert(filter != NULL);
1394 assert(value != NULL);
1395
1396 if (unlikely(type >= NFCT_FILTER_MAX))
1397 return;
1398
1399 if (filter_attr_array[type]) {
1400 filter_attr_array[type](filter, value);
1401 set_bit(type, filter->set);
1402 }
1403}
1404
1413void nfct_filter_add_attr_u32(struct nfct_filter *filter,
1414 const enum nfct_filter_attr type,
1415 uint32_t value)
1416{
1417 nfct_filter_add_attr(filter, type, &value);
1418}
1419
1435int nfct_filter_set_logic(struct nfct_filter *filter,
1436 const enum nfct_filter_attr type,
1437 const enum nfct_filter_logic logic)
1438{
1439 if (unlikely(type >= NFCT_FILTER_MAX)) {
1440 errno = ENOTSUP;
1441 return -1;
1442 }
1443
1444 if (filter->logic[type]) {
1445 errno = EBUSY;
1446 return -1;
1447 }
1448
1449 filter->logic[type] = logic;
1450
1451 return 0;
1452}
1453
1463int nfct_filter_attach(int fd, struct nfct_filter *filter)
1464{
1465 assert(filter != NULL);
1466
1467 return __setup_netlink_socket_filter(fd, filter);
1468}
1469
1477{
1478 int val = 0;
1479
1480 return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val));
1481}
1482
1499struct nfct_filter_dump *nfct_filter_dump_create(void)
1500{
1501 return calloc(sizeof(struct nfct_filter_dump), 1);
1502}
1503
1510void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
1511{
1512 assert(filter != NULL);
1513 free(filter);
1514 filter = NULL;
1515}
1516
1523void nfct_filter_dump_set_attr(struct nfct_filter_dump *filter_dump,
1524 const enum nfct_filter_dump_attr type,
1525 const void *value)
1526{
1527 assert(filter_dump != NULL);
1528 assert(value != NULL);
1529
1530 if (unlikely(type >= NFCT_FILTER_DUMP_MAX))
1531 return;
1532
1533 if (set_filter_dump_attr_array[type]) {
1534 set_filter_dump_attr_array[type](filter_dump, value);
1535 filter_dump->set |= (1 << type);
1536 }
1537}
1538
1545void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump,
1546 const enum nfct_filter_dump_attr type,
1547 uint8_t value)
1548{
1549 nfct_filter_dump_set_attr(filter_dump, type, &value);
1550}
1551
1568const char *nfct_labels_get_path(void)
1569{
1570 return __labels_get_path();
1571}
1572
1583const char *nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
1584{
1585 return __labelmap_get_name(m, bit);
1586}
1587
1596int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)
1597{
1598 return __labelmap_get_bit(m, name);
1599}
1600
1609struct nfct_labelmap *nfct_labelmap_new(const char *mapfile)
1610{
1611 return __labelmap_new(mapfile);
1612}
1613
1622{
1623 __labelmap_destroy(map);
1624}
1625
1630/*
1631 * \defgroup bitmask bitmask object
1632 *
1633 * @{
1634 */
1635
1644struct nfct_bitmask *nfct_bitmask_new(unsigned int max)
1645{
1646 struct nfct_bitmask *b;
1647 unsigned int bytes, words;
1648
1649 if (max > 0xffff)
1650 return NULL;
1651
1652 words = DIV_ROUND_UP(max+1, 32);
1653 bytes = words * sizeof(b->bits[0]);
1654
1655 b = malloc(sizeof(*b) + bytes);
1656 if (b) {
1657 memset(b->bits, 0, bytes);
1658 b->words = words;
1659 }
1660 return b;
1661}
1662
1663/*
1664 * nfct_bitmask_clone - duplicate a bitmask object
1665 *
1666 * \param b pointer to the bitmask object to duplicate
1667 *
1668 * returns an identical copy of the bitmask.
1669 */
1670struct nfct_bitmask *nfct_bitmask_clone(const struct nfct_bitmask *b)
1671{
1672 unsigned int bytes = b->words * sizeof(b->bits[0]);
1673 struct nfct_bitmask *copy;
1674
1675 bytes += sizeof(*b);
1676
1677 copy = malloc(bytes);
1678 if (copy)
1679 memcpy(copy, b, bytes);
1680 return copy;
1681}
1682
1683/*
1684 * nfct_bitmask_set_bit - set bit in the bitmask
1685 *
1686 * \param b pointer to the bitmask object
1687 * \param bit the bit to set
1688 */
1689void nfct_bitmask_set_bit(struct nfct_bitmask *b, unsigned int bit)
1690{
1691 unsigned int bits = b->words * 32;
1692 if (bit < bits)
1693 set_bit(bit, b->bits);
1694}
1695
1696/*
1697 * nfct_bitmask_test_bit - test if a bit in the bitmask is set
1698 *
1699 * \param b pointer to the bitmask object
1700 * \param bit the bit to test
1701 *
1702 * returns 0 if the bit is not set.
1703 */
1704int nfct_bitmask_test_bit(const struct nfct_bitmask *b, unsigned int bit)
1705{
1706 unsigned int bits = b->words * 32;
1707 return bit < bits && test_bit(bit, b->bits);
1708}
1709
1710/*
1711 * nfct_bitmask_unset_bit - unset bit in the bitmask
1712 *
1713 * \param b pointer to the bitmask object
1714 * \param bit the bit to clear
1715 */
1716void nfct_bitmask_unset_bit(struct nfct_bitmask *b, unsigned int bit)
1717{
1718 unsigned int bits = b->words * 32;
1719 if (bit < bits)
1720 unset_bit(bit, b->bits);
1721}
1722
1723/*
1724 * nfct_bitmask_maxbit - return highest bit that may be set/unset
1725 *
1726 * \param b pointer to the bitmask object
1727 */
1728unsigned int nfct_bitmask_maxbit(const struct nfct_bitmask *b)
1729{
1730 return (b->words * 32) - 1;
1731}
1732
1733/*
1734 * nfct_bitmask_destroy - destroy bitmask object
1735 *
1736 * \param b pointer to the bitmask object
1737 *
1738 * This function releases the memory that is used by the bitmask object.
1739 *
1740 * If you assign a bitmask object to a nf_conntrack object using
1741 * nfct_set_attr ATTR_CONNLABEL, then the ownership of the bitmask
1742 * object passes on to the nf_conntrack object. The nfct_bitmask object
1743 * will be destroyed when the nf_conntrack object is destroyed.
1744 */
1745void nfct_bitmask_destroy(struct nfct_bitmask *b)
1746{
1747 free(b);
1748}
1749
1750/*
1751 * nfct_bitmask_clear - clear a bitmask object
1752 *
1753 * \param b pointer to the bitmask object to clear
1754 */
1755void nfct_bitmask_clear(struct nfct_bitmask *b)
1756{
1757 unsigned int bytes = b->words * sizeof(b->bits[0]);
1758 memset(b->bits, 0, bytes);
1759}
1760
1761/*
1762 * nfct_bitmask_equal - compare two bitmask objects
1763 *
1764 * \param b1 pointer to a valid bitmask object
1765 * \param b2 pointer to a valid bitmask object
1766 *
1767 * If both bitmask object are equal, this function returns true, otherwise
1768 * false is returned.
1769 */
1770bool nfct_bitmask_equal(const struct nfct_bitmask *b1, const struct nfct_bitmask *b2)
1771{
1772 if (b1->words != b2->words)
1773 return false;
1774
1775 return memcmp(b1->bits, b2->bits, b1->words * sizeof(b1->bits[0])) == 0;
1776}
1777
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)
Definition: conntrack/api.c:93
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)
Definition: conntrack/api.c:76
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)