libnetfilter_conntrack  1.0.8
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 
76 struct 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 
93 void 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 
114 size_t nfct_sizeof(const struct nf_conntrack *ct)
115 {
116  assert(ct != NULL);
117  return sizeof(*ct);
118 }
119 
136 size_t nfct_maxsize(void)
137 {
138  return sizeof(struct nf_conntrack);
139 }
140 
148 struct 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 
169 int 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 
189 int 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 
224 int 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 
264 void 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 
298 int 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 
338 void 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 
369 void
370 nfct_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 
399 void 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 
413 void 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 
426 void 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 
439 void 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 
452 void 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 
467 const 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 
496 uint8_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 
512 uint16_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 
528 uint32_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 
544 uint64_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 
559 int 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 
580 int 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 
607 int 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 
630 void 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 
655 int 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 
695 int 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 
731 int 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 
771 int 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 
785 static 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 
803 static 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_DUMP:
835  nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, *family,
836  NFNETLINK_V0);
837  break;
838  case NFCT_Q_DUMP_RESET:
839  nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
840  *family, NFNETLINK_V0);
841  break;
842  case NFCT_Q_CREATE_UPDATE:
843  __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data);
844  break;
845  case NFCT_Q_DUMP_FILTER:
846  nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, AF_UNSPEC,
847  NFNETLINK_V0);
848  __build_filter_dump(req, size, data);
849  break;
850  case NFCT_Q_DUMP_FILTER_RESET:
851  nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
852  AF_UNSPEC, NFNETLINK_V0);
853  __build_filter_dump(req, size, data);
854  break;
855  default:
856  errno = ENOTSUP;
857  return -1;
858  }
859  return 1;
860 }
861 
898 int nfct_build_query(struct nfnl_subsys_handle *ssh,
899  const enum nf_conntrack_query qt,
900  const void *data,
901  void *buffer,
902  unsigned int size)
903 {
904  return __build_query_ct(ssh, qt, data, buffer, size);
905 }
906 
907 static int __parse_message_type(const struct nlmsghdr *nlh)
908 {
909  uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
910  uint16_t flags = nlh->nlmsg_flags;
911  int ret = NFCT_T_UNKNOWN;
912 
913  if (type == IPCTNL_MSG_CT_NEW) {
914  if (flags & (NLM_F_CREATE|NLM_F_EXCL))
915  ret = NFCT_T_NEW;
916  else
917  ret = NFCT_T_UPDATE;
918  } else if (type == IPCTNL_MSG_CT_DELETE)
919  ret = NFCT_T_DESTROY;
920 
921  return ret;
922 }
923 
948 int nfct_parse_conntrack(enum nf_conntrack_msg_type type,
949  const struct nlmsghdr *nlh,
950  struct nf_conntrack *ct)
951 {
952  unsigned int flags;
953 
954  assert(nlh != NULL);
955  assert(ct != NULL);
956 
957  flags = __parse_message_type(nlh);
958  if (!(flags & type))
959  return 0;
960 
961  nfct_nlmsg_parse(nlh, ct);
962 
963  return flags;
964 }
965 
984 int nfct_query(struct nfct_handle *h,
985  const enum nf_conntrack_query qt,
986  const void *data)
987 {
988  const size_t size = 4096; /* enough for now */
989  union {
990  char buffer[size];
991  struct nfnlhdr req;
992  } u;
993 
994  assert(h != NULL);
995  assert(data != NULL);
996 
997  if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
998  return -1;
999 
1000  return nfnl_query(h->nfnlh, &u.req.nlh);
1001 }
1002 
1016 int nfct_send(struct nfct_handle *h,
1017  const enum nf_conntrack_query qt,
1018  const void *data)
1019 {
1020  const size_t size = 4096; /* enough for now */
1021  union {
1022  char buffer[size];
1023  struct nfnlhdr req;
1024  } u;
1025 
1026  assert(h != NULL);
1027  assert(data != NULL);
1028 
1029  if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1030  return -1;
1031 
1032  return nfnl_send(h->nfnlh, &u.req.nlh);
1033 }
1034 
1035 
1050 int nfct_catch(struct nfct_handle *h)
1051 {
1052  assert(h != NULL);
1053 
1054  return nfnl_catch(h->nfnlh);
1055 }
1056 
1106 int nfct_snprintf(char *buf,
1107  unsigned int size,
1108  const struct nf_conntrack *ct,
1109  unsigned int msg_type,
1110  unsigned int out_type,
1111  unsigned int flags)
1112 {
1113  assert(buf != NULL);
1114  assert(size > 0);
1115  assert(ct != NULL);
1116 
1117  return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, NULL);
1118 }
1119 
1134 int nfct_snprintf_labels(char *buf,
1135  unsigned int size,
1136  const struct nf_conntrack *ct,
1137  unsigned int msg_type,
1138  unsigned int out_type,
1139  unsigned int flags,
1140  struct nfct_labelmap *map)
1141 {
1142  return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, map);
1143 }
1144 
1159 int nfct_compare(const struct nf_conntrack *ct1,
1160  const struct nf_conntrack *ct2)
1161 {
1162  assert(ct1 != NULL);
1163  assert(ct2 != NULL);
1164 
1165  return __compare(ct1, ct2, NFCT_CMP_ALL);
1166 }
1167 
1205 int nfct_cmp(const struct nf_conntrack *ct1,
1206  const struct nf_conntrack *ct2,
1207  unsigned int flags)
1208 {
1209  assert(ct1 != NULL);
1210  assert(ct2 != NULL);
1211 
1212  return __compare(ct1, ct2, flags);
1213 }
1214 
1240 void nfct_copy(struct nf_conntrack *ct1,
1241  const struct nf_conntrack *ct2,
1242  unsigned int flags)
1243 {
1244  int i;
1245 
1246  assert(ct1 != NULL);
1247  assert(ct2 != NULL);
1248 
1249  if (flags & NFCT_CP_OVERRIDE) {
1250  __copy_fast(ct1, ct2);
1251  return;
1252  }
1253  if (flags == NFCT_CP_ALL) {
1254  for (i=0; i<ATTR_MAX; i++) {
1255  if (test_bit(i, ct2->head.set)) {
1256  assert(copy_attr_array[i]);
1257  copy_attr_array[i](ct1, ct2);
1258  set_bit(i, ct1->head.set);
1259  }
1260  }
1261  return;
1262  }
1263 
1264  static const int cp_orig_mask[] = {
1265  ATTR_ORIG_IPV4_SRC,
1266  ATTR_ORIG_IPV4_DST,
1267  ATTR_ORIG_IPV6_SRC,
1268  ATTR_ORIG_IPV6_DST,
1269  ATTR_ORIG_PORT_SRC,
1270  ATTR_ORIG_PORT_DST,
1271  ATTR_ICMP_TYPE,
1272  ATTR_ICMP_CODE,
1273  ATTR_ICMP_ID,
1274  ATTR_ORIG_L3PROTO,
1275  ATTR_ORIG_L4PROTO,
1276  };
1277  #define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int)
1278 
1279  if (flags & NFCT_CP_ORIG) {
1280  for (i=0; i<__CP_ORIG_MAX; i++) {
1281  if (test_bit(cp_orig_mask[i], ct2->head.set)) {
1282  assert(copy_attr_array[i]);
1283  copy_attr_array[cp_orig_mask[i]](ct1, ct2);
1284  set_bit(cp_orig_mask[i], ct1->head.set);
1285  }
1286  }
1287  }
1288 
1289  static const int cp_repl_mask[] = {
1290  ATTR_REPL_IPV4_SRC,
1291  ATTR_REPL_IPV4_DST,
1292  ATTR_REPL_IPV6_SRC,
1293  ATTR_REPL_IPV6_DST,
1294  ATTR_REPL_PORT_SRC,
1295  ATTR_REPL_PORT_DST,
1296  ATTR_REPL_L3PROTO,
1297  ATTR_REPL_L4PROTO,
1298  };
1299  #define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int)
1300 
1301  if (flags & NFCT_CP_REPL) {
1302  for (i=0; i<__CP_REPL_MAX; i++) {
1303  if (test_bit(cp_repl_mask[i], ct2->head.set)) {
1304  assert(copy_attr_array[i]);
1305  copy_attr_array[cp_repl_mask[i]](ct1, ct2);
1306  set_bit(cp_repl_mask[i], ct1->head.set);
1307  }
1308  }
1309  }
1310 
1311  if (flags & NFCT_CP_META) {
1312  for (i=ATTR_TCP_STATE; i<ATTR_MAX; i++) {
1313  if (test_bit(i, ct2->head.set)) {
1314  assert(copy_attr_array[i]),
1315  copy_attr_array[i](ct1, ct2);
1316  set_bit(i, ct1->head.set);
1317  }
1318  }
1319  }
1320 }
1321 
1330 void nfct_copy_attr(struct nf_conntrack *ct1,
1331  const struct nf_conntrack *ct2,
1332  const enum nf_conntrack_attr type)
1333 {
1334  if (test_bit(type, ct2->head.set)) {
1335  assert(copy_attr_array[type]);
1336  copy_attr_array[type](ct1, ct2);
1337  set_bit(type, ct1->head.set);
1338  }
1339 }
1340 
1357 struct nfct_filter *nfct_filter_create(void)
1358 {
1359  return calloc(sizeof(struct nfct_filter), 1);
1360 }
1361 
1370 void nfct_filter_destroy(struct nfct_filter *filter)
1371 {
1372  assert(filter != NULL);
1373  free(filter);
1374  filter = NULL;
1375 }
1376 
1386 void nfct_filter_add_attr(struct nfct_filter *filter,
1387  const enum nfct_filter_attr type,
1388  const void *value)
1389 {
1390  assert(filter != NULL);
1391  assert(value != NULL);
1392 
1393  if (unlikely(type >= NFCT_FILTER_MAX))
1394  return;
1395 
1396  if (filter_attr_array[type]) {
1397  filter_attr_array[type](filter, value);
1398  set_bit(type, filter->set);
1399  }
1400 }
1401 
1410 void nfct_filter_add_attr_u32(struct nfct_filter *filter,
1411  const enum nfct_filter_attr type,
1412  uint32_t value)
1413 {
1414  nfct_filter_add_attr(filter, type, &value);
1415 }
1416 
1432 int nfct_filter_set_logic(struct nfct_filter *filter,
1433  const enum nfct_filter_attr type,
1434  const enum nfct_filter_logic logic)
1435 {
1436  if (unlikely(type >= NFCT_FILTER_MAX)) {
1437  errno = ENOTSUP;
1438  return -1;
1439  }
1440 
1441  if (filter->logic[type]) {
1442  errno = EBUSY;
1443  return -1;
1444  }
1445 
1446  filter->logic[type] = logic;
1447 
1448  return 0;
1449 }
1450 
1460 int nfct_filter_attach(int fd, struct nfct_filter *filter)
1461 {
1462  assert(filter != NULL);
1463 
1464  return __setup_netlink_socket_filter(fd, filter);
1465 }
1466 
1474 {
1475  int val = 0;
1476 
1477  return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val));
1478 }
1479 
1496 struct nfct_filter_dump *nfct_filter_dump_create(void)
1497 {
1498  return calloc(sizeof(struct nfct_filter_dump), 1);
1499 }
1500 
1507 void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
1508 {
1509  assert(filter != NULL);
1510  free(filter);
1511  filter = NULL;
1512 }
1513 
1520 void nfct_filter_dump_set_attr(struct nfct_filter_dump *filter_dump,
1521  const enum nfct_filter_dump_attr type,
1522  const void *value)
1523 {
1524  assert(filter_dump != NULL);
1525  assert(value != NULL);
1526 
1527  if (unlikely(type >= NFCT_FILTER_DUMP_MAX))
1528  return;
1529 
1530  if (set_filter_dump_attr_array[type]) {
1531  set_filter_dump_attr_array[type](filter_dump, value);
1532  filter_dump->set |= (1 << type);
1533  }
1534 }
1535 
1542 void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump,
1543  const enum nfct_filter_dump_attr type,
1544  uint8_t value)
1545 {
1546  nfct_filter_dump_set_attr(filter_dump, type, &value);
1547 }
1548 
1565 const char *nfct_labels_get_path(void)
1566 {
1567  return __labels_get_path();
1568 }
1569 
1580 const char *nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
1581 {
1582  return __labelmap_get_name(m, bit);
1583 }
1584 
1593 int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)
1594 {
1595  return __labelmap_get_bit(m, name);
1596 }
1597 
1606 struct nfct_labelmap *nfct_labelmap_new(const char *mapfile)
1607 {
1608  return __labelmap_new(mapfile);
1609 }
1610 
1619 {
1620  __labelmap_destroy(map);
1621 }
1622 
1627 /*
1628  * \defgroup bitmask bitmask object
1629  *
1630  * @{
1631  */
1632 
1641 struct nfct_bitmask *nfct_bitmask_new(unsigned int max)
1642 {
1643  struct nfct_bitmask *b;
1644  unsigned int bytes, words;
1645 
1646  if (max > 0xffff)
1647  return NULL;
1648 
1649  words = DIV_ROUND_UP(max+1, 32);
1650  bytes = words * sizeof(b->bits[0]);
1651 
1652  b = malloc(sizeof(*b) + bytes);
1653  if (b) {
1654  memset(b->bits, 0, bytes);
1655  b->words = words;
1656  }
1657  return b;
1658 }
1659 
1660 /*
1661  * nfct_bitmask_clone - duplicate a bitmask object
1662  *
1663  * \param b pointer to the bitmask object to duplicate
1664  *
1665  * returns an identical copy of the bitmask.
1666  */
1667 struct nfct_bitmask *nfct_bitmask_clone(const struct nfct_bitmask *b)
1668 {
1669  unsigned int bytes = b->words * sizeof(b->bits[0]);
1670  struct nfct_bitmask *copy;
1671 
1672  bytes += sizeof(*b);
1673 
1674  copy = malloc(bytes);
1675  if (copy)
1676  memcpy(copy, b, bytes);
1677  return copy;
1678 }
1679 
1680 /*
1681  * nfct_bitmask_set_bit - set bit in the bitmask
1682  *
1683  * \param b pointer to the bitmask object
1684  * \param bit the bit to set
1685  */
1686 void nfct_bitmask_set_bit(struct nfct_bitmask *b, unsigned int bit)
1687 {
1688  unsigned int bits = b->words * 32;
1689  if (bit < bits)
1690  set_bit(bit, b->bits);
1691 }
1692 
1693 /*
1694  * nfct_bitmask_test_bit - test if a bit in the bitmask is set
1695  *
1696  * \param b pointer to the bitmask object
1697  * \param bit the bit to test
1698  *
1699  * returns 0 if the bit is not set.
1700  */
1701 int nfct_bitmask_test_bit(const struct nfct_bitmask *b, unsigned int bit)
1702 {
1703  unsigned int bits = b->words * 32;
1704  return bit < bits && test_bit(bit, b->bits);
1705 }
1706 
1707 /*
1708  * nfct_bitmask_unset_bit - unset bit in the bitmask
1709  *
1710  * \param b pointer to the bitmask object
1711  * \param bit the bit to clear
1712  */
1713 void nfct_bitmask_unset_bit(struct nfct_bitmask *b, unsigned int bit)
1714 {
1715  unsigned int bits = b->words * 32;
1716  if (bit < bits)
1717  unset_bit(bit, b->bits);
1718 }
1719 
1720 /*
1721  * nfct_bitmask_maxbit - return highest bit that may be set/unset
1722  *
1723  * \param b pointer to the bitmask object
1724  */
1725 unsigned int nfct_bitmask_maxbit(const struct nfct_bitmask *b)
1726 {
1727  return (b->words * 32) - 1;
1728 }
1729 
1730 /*
1731  * nfct_bitmask_destroy - destroy bitmask object
1732  *
1733  * \param b pointer to the bitmask object
1734  *
1735  * This function releases the memory that is used by the bitmask object.
1736  *
1737  * If you assign a bitmask object to a nf_conntrack object using
1738  * nfct_set_attr ATTR_CONNLABEL, then the ownership of the bitmask
1739  * object passes on to the nf_conntrack object. The nfct_bitmask object
1740  * will be destroyed when the nf_conntrack object is destroyed.
1741  */
1742 void nfct_bitmask_destroy(struct nfct_bitmask *b)
1743 {
1744  free(b);
1745 }
1746 
1747 /*
1748  * nfct_bitmask_clear - clear a bitmask object
1749  *
1750  * \param b pointer to the bitmask object to clear
1751  */
1752 void nfct_bitmask_clear(struct nfct_bitmask *b)
1753 {
1754  unsigned int bytes = b->words * sizeof(b->bits[0]);
1755  memset(b->bits, 0, bytes);
1756 }
1757 
1758 /*
1759  * nfct_bitmask_equal - compare two bitmask objects
1760  *
1761  * \param b1 pointer to a valid bitmask object
1762  * \param b2 pointer to a valid bitmask object
1763  *
1764  * If both bitmask object are equal, this function returns true, otherwise
1765  * false is returned.
1766  */
1767 bool nfct_bitmask_equal(const struct nfct_bitmask *b1, const struct nfct_bitmask *b2)
1768 {
1769  if (b1->words != b2->words)
1770  return false;
1771 
1772  return memcmp(b1->bits, b2->bits, b1->words * sizeof(b1->bits[0])) == 0;
1773 }
1774 
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)
const void * nfct_get_attr(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
struct nf_conntrack * nfct_new(void)
Definition: conntrack/api.c:76
void nfct_set_attr(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value)
int nfct_attr_grp_unset(struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type)
uint64_t nfct_get_attr_u64(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_setobjopt(struct nf_conntrack *ct, unsigned int option)
int nfct_get_attr_grp(const struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type, void *data)
void nfct_set_attr_grp(struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type, const void *data)
int nfct_attr_is_set_array(const struct nf_conntrack *ct, const enum nf_conntrack_attr *type_array, int size)
int nfct_attr_unset(struct nf_conntrack *ct, const enum nf_conntrack_attr type)
void nfct_copy(struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags)
uint16_t nfct_get_attr_u16(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_attr_grp_is_set(const struct nf_conntrack *ct, const enum nf_conntrack_attr_grp type)
int nfct_cmp(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags)
struct nf_conntrack * nfct_clone(const struct nf_conntrack *ct)
void nfct_set_attr_u16(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint16_t value)
uint32_t nfct_get_attr_u32(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
void nfct_set_attr_u8(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint8_t value)
void nfct_set_attr_u64(struct nf_conntrack *ct, const enum nf_conntrack_attr type, uint64_t value)
void nfct_set_attr_l(struct nf_conntrack *ct, const enum nf_conntrack_attr type, const void *value, size_t len)
int nfct_snprintf(char *buf, unsigned int size, const struct nf_conntrack *ct, unsigned int msg_type, unsigned int out_type, unsigned int flags)
size_t nfct_maxsize(void)
int nfct_attr_is_set(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
int nfct_getobjopt(const struct nf_conntrack *ct, unsigned int option)
int nfct_compare(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2)
uint8_t nfct_get_attr_u8(const struct nf_conntrack *ct, const enum nf_conntrack_attr type)
void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump, const enum nfct_filter_dump_attr type, uint8_t value)
void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
struct nfct_filter_dump * nfct_filter_dump_create(void)
void nfct_filter_dump_set_attr(struct nfct_filter_dump *filter_dump, const enum nfct_filter_dump_attr type, const void *value)
const char * nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
struct nfct_labelmap * nfct_labelmap_new(const char *mapfile)
void nfct_labelmap_destroy(struct nfct_labelmap *map)
const char * nfct_labels_get_path(void)
int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)
int nfct_parse_conntrack(enum nf_conntrack_msg_type type, const struct nlmsghdr *nlh, struct nf_conntrack *ct)
int nfct_build_conntrack(struct nfnl_subsys_handle *ssh, void *req, size_t size, uint16_t type, uint16_t flags, const struct nf_conntrack *ct)
int nfct_build_query(struct nfnl_subsys_handle *ssh, const enum nf_conntrack_query qt, const void *data, void *buffer, unsigned int size)