libnetfilter_conntrack  1.0.6
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 
16 #include "internal/internal.h"
17 
75 struct nf_conntrack *nfct_new(void)
76 {
77  struct nf_conntrack *ct;
78 
79  ct = malloc(sizeof(struct nf_conntrack));
80  if (!ct)
81  return NULL;
82 
83  memset(ct, 0, sizeof(struct nf_conntrack));
84 
85  return ct;
86 }
87 
92 void nfct_destroy(struct nf_conntrack *ct)
93 {
94  assert(ct != NULL);
95  if (ct->secctx)
96  free(ct->secctx);
97  if (ct->helper_info)
98  free(ct->helper_info);
99  if (ct->connlabels)
100  nfct_bitmask_destroy(ct->connlabels);
101  if (ct->connlabels_mask)
102  nfct_bitmask_destroy(ct->connlabels_mask);
103  free(ct);
104  ct = NULL; /* bugtrap */
105 }
106 
113 size_t nfct_sizeof(const struct nf_conntrack *ct)
114 {
115  assert(ct != NULL);
116  return sizeof(*ct);
117 }
118 
135 size_t nfct_maxsize(void)
136 {
137  return sizeof(struct nf_conntrack);
138 }
139 
147 struct nf_conntrack *nfct_clone(const struct nf_conntrack *ct)
148 {
149  struct nf_conntrack *clone;
150 
151  assert(ct != NULL);
152 
153  if ((clone = nfct_new()) == NULL)
154  return NULL;
155  nfct_copy(clone, ct, NFCT_CP_OVERRIDE);
156 
157  return clone;
158 }
159 
168 int nfct_setobjopt(struct nf_conntrack *ct, unsigned int option)
169 {
170  assert(ct != NULL);
171 
172  if (unlikely(option > NFCT_SOPT_MAX)) {
173  errno = EOPNOTSUPP;
174  return -1;
175  }
176 
177  return __setobjopt(ct, option);
178 }
179 
188 int nfct_getobjopt(const struct nf_conntrack *ct, unsigned int option)
189 {
190  assert(ct != NULL);
191 
192  if (unlikely(option > NFCT_GOPT_MAX)) {
193  errno = EOPNOTSUPP;
194  return -1;
195  }
196 
197  return __getobjopt(ct, option);
198 }
199 
223 int nfct_callback_register(struct nfct_handle *h,
224  enum nf_conntrack_msg_type type,
225  int (*cb)(enum nf_conntrack_msg_type type,
226  struct nf_conntrack *ct,
227  void *data),
228  void *data)
229 {
230  struct __data_container *container;
231 
232  assert(h != NULL);
233 
234  container = malloc(sizeof(struct __data_container));
235  if (!container)
236  return -1;
237  memset(container, 0, sizeof(struct __data_container));
238 
239  h->cb = cb;
240  container->h = h;
241  container->type = type;
242  container->data = data;
243 
244  h->nfnl_cb_ct.call = __callback;
245  h->nfnl_cb_ct.data = container;
246  h->nfnl_cb_ct.attr_count = CTA_MAX;
247 
248  nfnl_callback_register(h->nfnlssh_ct,
249  IPCTNL_MSG_CT_NEW,
250  &h->nfnl_cb_ct);
251 
252  nfnl_callback_register(h->nfnlssh_ct,
253  IPCTNL_MSG_CT_DELETE,
254  &h->nfnl_cb_ct);
255 
256  return 0;
257 }
258 
263 void nfct_callback_unregister(struct nfct_handle *h)
264 {
265  assert(h != NULL);
266 
267  nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
268  nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
269 
270  h->cb = NULL;
271  free(h->nfnl_cb_ct.data);
272 
273  h->nfnl_cb_ct.call = NULL;
274  h->nfnl_cb_ct.data = NULL;
275  h->nfnl_cb_ct.attr_count = 0;
276 }
277 
297 int nfct_callback_register2(struct nfct_handle *h,
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,
302  void *data),
303  void *data)
304 {
305  struct __data_container *container;
306 
307  assert(h != NULL);
308 
309  container = calloc(sizeof(struct __data_container), 1);
310  if (container == NULL)
311  return -1;
312 
313  h->cb2 = cb;
314  container->h = h;
315  container->type = type;
316  container->data = data;
317 
318  h->nfnl_cb_ct.call = __callback;
319  h->nfnl_cb_ct.data = container;
320  h->nfnl_cb_ct.attr_count = CTA_MAX;
321 
322  nfnl_callback_register(h->nfnlssh_ct,
323  IPCTNL_MSG_CT_NEW,
324  &h->nfnl_cb_ct);
325 
326  nfnl_callback_register(h->nfnlssh_ct,
327  IPCTNL_MSG_CT_DELETE,
328  &h->nfnl_cb_ct);
329 
330  return 0;
331 }
332 
337 void nfct_callback_unregister2(struct nfct_handle *h)
338 {
339  assert(h != NULL);
340 
341  nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
342  nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
343 
344  h->cb2 = NULL;
345  free(h->nfnl_cb_ct.data);
346 
347  h->nfnl_cb_ct.call = NULL;
348  h->nfnl_cb_ct.data = NULL;
349  h->nfnl_cb_ct.attr_count = 0;
350 }
351 
368 void
369 nfct_set_attr_l(struct nf_conntrack *ct, const enum nf_conntrack_attr type,
370  const void *value, size_t len)
371 {
372  assert(ct != NULL);
373  assert(value != NULL);
374 
375  if (unlikely(type >= ATTR_MAX))
376  return;
377 
378  if (set_attr_array[type]) {
379  set_attr_array[type](ct, value, len);
380  set_bit(type, ct->head.set);
381  }
382 }
383 
398 void nfct_set_attr(struct nf_conntrack *ct,
399  const enum nf_conntrack_attr type,
400  const void *value)
401 {
402  /* We assume the setter knows the size of the passed pointer. */
403  nfct_set_attr_l(ct, type, value, 0);
404 }
405 
412 void nfct_set_attr_u8(struct nf_conntrack *ct,
413  const enum nf_conntrack_attr type,
414  uint8_t value)
415 {
416  nfct_set_attr_l(ct, type, &value, sizeof(uint8_t));
417 }
418 
425 void nfct_set_attr_u16(struct nf_conntrack *ct,
426  const enum nf_conntrack_attr type,
427  uint16_t value)
428 {
429  nfct_set_attr_l(ct, type, &value, sizeof(uint16_t));
430 }
431 
438 void nfct_set_attr_u32(struct nf_conntrack *ct,
439  const enum nf_conntrack_attr type,
440  uint32_t value)
441 {
442  nfct_set_attr_l(ct, type, &value, sizeof(uint32_t));
443 }
444 
451 void nfct_set_attr_u64(struct nf_conntrack *ct,
452  const enum nf_conntrack_attr type,
453  uint64_t value)
454 {
455  nfct_set_attr_l(ct, type, &value, sizeof(uint64_t));
456 }
457 
466 const void *nfct_get_attr(const struct nf_conntrack *ct,
467  const enum nf_conntrack_attr type)
468 {
469  assert(ct != NULL);
470 
471  if (unlikely(type >= ATTR_MAX)) {
472  errno = EINVAL;
473  return NULL;
474  }
475 
476  if (!test_bit(type, ct->head.set)) {
477  errno = ENODATA;
478  return NULL;
479  }
480 
481  assert(get_attr_array[type]);
482 
483  return get_attr_array[type](ct);
484 }
485 
495 uint8_t nfct_get_attr_u8(const struct nf_conntrack *ct,
496  const enum nf_conntrack_attr type)
497 {
498  const uint8_t *ret = nfct_get_attr(ct, type);
499  return ret == NULL ? 0 : *ret;
500 }
501 
511 uint16_t nfct_get_attr_u16(const struct nf_conntrack *ct,
512  const enum nf_conntrack_attr type)
513 {
514  const uint16_t *ret = nfct_get_attr(ct, type);
515  return ret == NULL ? 0 : *ret;
516 }
517 
527 uint32_t nfct_get_attr_u32(const struct nf_conntrack *ct,
528  const enum nf_conntrack_attr type)
529 {
530  const uint32_t *ret = nfct_get_attr(ct, type);
531  return ret == NULL ? 0 : *ret;
532 }
533 
543 uint64_t nfct_get_attr_u64(const struct nf_conntrack *ct,
544  const enum nf_conntrack_attr type)
545 {
546  const uint64_t *ret = nfct_get_attr(ct, type);
547  return ret == NULL ? 0 : *ret;
548 }
549 
558 int nfct_attr_is_set(const struct nf_conntrack *ct,
559  const enum nf_conntrack_attr type)
560 {
561  assert(ct != NULL);
562 
563  if (unlikely(type >= ATTR_MAX)) {
564  errno = EINVAL;
565  return -1;
566  }
567  return test_bit(type, ct->head.set);
568 }
569 
579 int nfct_attr_is_set_array(const struct nf_conntrack *ct,
580  const enum nf_conntrack_attr *type_array,
581  int size)
582 {
583  int i;
584 
585  assert(ct != NULL);
586 
587  for (i=0; i<size; i++) {
588  if (unlikely(type_array[i] >= ATTR_MAX)) {
589  errno = EINVAL;
590  return -1;
591  }
592  if (!test_bit(type_array[i], ct->head.set))
593  return 0;
594  }
595  return 1;
596 }
597 
606 int nfct_attr_unset(struct nf_conntrack *ct,
607  const enum nf_conntrack_attr type)
608 {
609  assert(ct != NULL);
610 
611  if (unlikely(type >= ATTR_MAX)) {
612  errno = EINVAL;
613  return -1;
614  }
615  unset_bit(type, ct->head.set);
616 
617  return 0;
618 }
619 
629 void nfct_set_attr_grp(struct nf_conntrack *ct,
630  const enum nf_conntrack_attr_grp type,
631  const void *data)
632 {
633  assert(ct != NULL);
634 
635  if (unlikely(type >= ATTR_GRP_MAX))
636  return;
637 
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);
642  }
643 }
644 
654 int nfct_get_attr_grp(const struct nf_conntrack *ct,
655  const enum nf_conntrack_attr_grp type,
656  void *data)
657 {
658  assert(ct != NULL);
659 
660  if (unlikely(type >= ATTR_GRP_MAX)) {
661  errno = EINVAL;
662  return -1;
663  }
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,
668  __NFCT_BITSET)) {
669  errno = ENODATA;
670  return -1;
671  }
672  break;
673  case NFCT_BITMASK_OR:
674  if (!test_bitmask_u32_or(ct->head.set,
675  attr_grp_bitmask[type].bitmask,
676  __NFCT_BITSET)) {
677  errno = ENODATA;
678  return -1;
679  }
680  break;
681  }
682  assert(get_attr_grp_array[type]);
683  get_attr_grp_array[type](ct, data);
684  return 0;
685 }
686 
694 int nfct_attr_grp_is_set(const struct nf_conntrack *ct,
695  const enum nf_conntrack_attr_grp type)
696 {
697  assert(ct != NULL);
698 
699  if (unlikely(type >= ATTR_GRP_MAX)) {
700  errno = EINVAL;
701  return -1;
702  }
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,
707  __NFCT_BITSET)) {
708  return 1;
709  }
710  break;
711  case NFCT_BITMASK_OR:
712  if (test_bitmask_u32_or(ct->head.set,
713  attr_grp_bitmask[type].bitmask,
714  __NFCT_BITSET)) {
715  return 1;
716  }
717  break;
718  }
719  return 0;
720 }
721 
730 int nfct_attr_grp_unset(struct nf_conntrack *ct,
731  const enum nf_conntrack_attr_grp type)
732 {
733  assert(ct != NULL);
734 
735  if (unlikely(type >= ATTR_GRP_MAX)) {
736  errno = EINVAL;
737  return -1;
738  }
739  unset_bitmask_u32(ct->head.set, attr_grp_bitmask[type].bitmask,
740  __NFCT_BITSET);
741 
742  return 0;
743 }
744 
770 int nfct_build_conntrack(struct nfnl_subsys_handle *ssh,
771  void *req,
772  size_t size,
773  uint16_t type,
774  uint16_t flags,
775  const struct nf_conntrack *ct)
776 {
777  assert(ssh != NULL);
778  assert(req != NULL);
779  assert(ct != NULL);
780 
781  return __build_conntrack(ssh, req, size, type, flags, ct);
782 }
783 
784 static int
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)
788 {
789  struct nfnlhdr *req = buffer;
790  const uint32_t *family = data;
791 
792  assert(ssh != NULL);
793  assert(data != NULL);
794  assert(req != NULL);
795 
796  memset(req, 0, size);
797 
798  switch(qt) {
799  case NFCT_Q_CREATE:
800  __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
801  break;
802  case NFCT_Q_UPDATE:
803  __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK, data);
804  break;
805  case NFCT_Q_DESTROY:
806  __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
807  break;
808  case NFCT_Q_GET:
809  __build_conntrack(ssh, req, size, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_ACK, data);
810  break;
811  case NFCT_Q_FLUSH:
812  nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK);
813  break;
814  case NFCT_Q_DUMP:
815  nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_DUMP);
816  break;
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);
819  break;
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);
822  break;
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);
826  break;
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);
830  break;
831  default:
832  errno = ENOTSUP;
833  return -1;
834  }
835  return 1;
836 }
837 
874 int nfct_build_query(struct nfnl_subsys_handle *ssh,
875  const enum nf_conntrack_query qt,
876  const void *data,
877  void *buffer,
878  unsigned int size)
879 {
880  return __build_query_ct(ssh, qt, data, buffer, size);
881 }
882 
907 int nfct_parse_conntrack(enum nf_conntrack_msg_type type,
908  const struct nlmsghdr *nlh,
909  struct nf_conntrack *ct)
910 {
911  unsigned int flags;
912  int len = nlh->nlmsg_len;
913  struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
914  struct nfattr *cda[CTA_MAX];
915 
916  assert(nlh != NULL);
917  assert(ct != NULL);
918 
919  len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
920  if (len < 0) {
921  errno = EINVAL;
922  return NFCT_T_ERROR;
923  }
924 
925  flags = __parse_message_type(nlh);
926  if (!(flags & type))
927  return 0;
928 
929  nfnl_parse_attr(cda, CTA_MAX, NFA_DATA(nfhdr), len);
930 
931  __parse_conntrack(nlh, cda, ct);
932 
933  return flags;
934 }
935 
954 int nfct_query(struct nfct_handle *h,
955  const enum nf_conntrack_query qt,
956  const void *data)
957 {
958  const size_t size = 4096; /* enough for now */
959  union {
960  char buffer[size];
961  struct nfnlhdr req;
962  } u;
963 
964  assert(h != NULL);
965  assert(data != NULL);
966 
967  if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
968  return -1;
969 
970  return nfnl_query(h->nfnlh, &u.req.nlh);
971 }
972 
986 int nfct_send(struct nfct_handle *h,
987  const enum nf_conntrack_query qt,
988  const void *data)
989 {
990  const size_t size = 4096; /* enough for now */
991  union {
992  char buffer[size];
993  struct nfnlhdr req;
994  } u;
995 
996  assert(h != NULL);
997  assert(data != NULL);
998 
999  if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1000  return -1;
1001 
1002  return nfnl_send(h->nfnlh, &u.req.nlh);
1003 }
1004 
1005 
1020 int nfct_catch(struct nfct_handle *h)
1021 {
1022  assert(h != NULL);
1023 
1024  return nfnl_catch(h->nfnlh);
1025 }
1026 
1076 int nfct_snprintf(char *buf,
1077  unsigned int size,
1078  const struct nf_conntrack *ct,
1079  unsigned int msg_type,
1080  unsigned int out_type,
1081  unsigned int flags)
1082 {
1083  assert(buf != NULL);
1084  assert(size > 0);
1085  assert(ct != NULL);
1086 
1087  return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, NULL);
1088 }
1089 
1104 int nfct_snprintf_labels(char *buf,
1105  unsigned int size,
1106  const struct nf_conntrack *ct,
1107  unsigned int msg_type,
1108  unsigned int out_type,
1109  unsigned int flags,
1110  struct nfct_labelmap *map)
1111 {
1112  return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, map);
1113 }
1114 
1129 int nfct_compare(const struct nf_conntrack *ct1,
1130  const struct nf_conntrack *ct2)
1131 {
1132  assert(ct1 != NULL);
1133  assert(ct2 != NULL);
1134 
1135  return __compare(ct1, ct2, NFCT_CMP_ALL);
1136 }
1137 
1175 int nfct_cmp(const struct nf_conntrack *ct1,
1176  const struct nf_conntrack *ct2,
1177  unsigned int flags)
1178 {
1179  assert(ct1 != NULL);
1180  assert(ct2 != NULL);
1181 
1182  return __compare(ct1, ct2, flags);
1183 }
1184 
1210 void nfct_copy(struct nf_conntrack *ct1,
1211  const struct nf_conntrack *ct2,
1212  unsigned int flags)
1213 {
1214  int i;
1215 
1216  assert(ct1 != NULL);
1217  assert(ct2 != NULL);
1218 
1219  if (flags & NFCT_CP_OVERRIDE) {
1220  __copy_fast(ct1, ct2);
1221  return;
1222  }
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);
1229  }
1230  }
1231  return;
1232  }
1233 
1234  static const int cp_orig_mask[] = {
1235  ATTR_ORIG_IPV4_SRC,
1236  ATTR_ORIG_IPV4_DST,
1237  ATTR_ORIG_IPV6_SRC,
1238  ATTR_ORIG_IPV6_DST,
1239  ATTR_ORIG_PORT_SRC,
1240  ATTR_ORIG_PORT_DST,
1241  ATTR_ICMP_TYPE,
1242  ATTR_ICMP_CODE,
1243  ATTR_ICMP_ID,
1244  ATTR_ORIG_L3PROTO,
1245  ATTR_ORIG_L4PROTO,
1246  };
1247  #define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int)
1248 
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);
1255  }
1256  }
1257  }
1258 
1259  static const int cp_repl_mask[] = {
1260  ATTR_REPL_IPV4_SRC,
1261  ATTR_REPL_IPV4_DST,
1262  ATTR_REPL_IPV6_SRC,
1263  ATTR_REPL_IPV6_DST,
1264  ATTR_REPL_PORT_SRC,
1265  ATTR_REPL_PORT_DST,
1266  ATTR_REPL_L3PROTO,
1267  ATTR_REPL_L4PROTO,
1268  };
1269  #define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int)
1270 
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);
1277  }
1278  }
1279  }
1280 
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);
1287  }
1288  }
1289  }
1290 }
1291 
1300 void nfct_copy_attr(struct nf_conntrack *ct1,
1301  const struct nf_conntrack *ct2,
1302  const enum nf_conntrack_attr type)
1303 {
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);
1308  }
1309 }
1310 
1327 struct nfct_filter *nfct_filter_create(void)
1328 {
1329  return calloc(sizeof(struct nfct_filter), 1);
1330 }
1331 
1340 void nfct_filter_destroy(struct nfct_filter *filter)
1341 {
1342  assert(filter != NULL);
1343  free(filter);
1344  filter = NULL;
1345 }
1346 
1356 void nfct_filter_add_attr(struct nfct_filter *filter,
1357  const enum nfct_filter_attr type,
1358  const void *value)
1359 {
1360  assert(filter != NULL);
1361  assert(value != NULL);
1362 
1363  if (unlikely(type >= NFCT_FILTER_MAX))
1364  return;
1365 
1366  if (filter_attr_array[type]) {
1367  filter_attr_array[type](filter, value);
1368  set_bit(type, filter->set);
1369  }
1370 }
1371 
1380 void nfct_filter_add_attr_u32(struct nfct_filter *filter,
1381  const enum nfct_filter_attr type,
1382  uint32_t value)
1383 {
1384  nfct_filter_add_attr(filter, type, &value);
1385 }
1386 
1402 int nfct_filter_set_logic(struct nfct_filter *filter,
1403  const enum nfct_filter_attr type,
1404  const enum nfct_filter_logic logic)
1405 {
1406  if (unlikely(type >= NFCT_FILTER_MAX)) {
1407  errno = ENOTSUP;
1408  return -1;
1409  }
1410 
1411  if (filter->logic[type]) {
1412  errno = EBUSY;
1413  return -1;
1414  }
1415 
1416  filter->logic[type] = logic;
1417 
1418  return 0;
1419 }
1420 
1430 int nfct_filter_attach(int fd, struct nfct_filter *filter)
1431 {
1432  assert(filter != NULL);
1433 
1434  return __setup_netlink_socket_filter(fd, filter);
1435 }
1436 
1444 {
1445  int val = 0;
1446 
1447  return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val));
1448 }
1449 
1466 struct nfct_filter_dump *nfct_filter_dump_create(void)
1467 {
1468  return calloc(sizeof(struct nfct_filter_dump), 1);
1469 }
1470 
1477 void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
1478 {
1479  assert(filter != NULL);
1480  free(filter);
1481  filter = NULL;
1482 }
1483 
1490 void nfct_filter_dump_set_attr(struct nfct_filter_dump *filter_dump,
1491  const enum nfct_filter_dump_attr type,
1492  const void *value)
1493 {
1494  assert(filter_dump != NULL);
1495  assert(value != NULL);
1496 
1497  if (unlikely(type >= NFCT_FILTER_DUMP_MAX))
1498  return;
1499 
1500  if (set_filter_dump_attr_array[type]) {
1501  set_filter_dump_attr_array[type](filter_dump, value);
1502  filter_dump->set |= (1 << type);
1503  }
1504 }
1505 
1512 void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump,
1513  const enum nfct_filter_dump_attr type,
1514  uint8_t value)
1515 {
1516  nfct_filter_dump_set_attr(filter_dump, type, &value);
1517 }
1518 
1535 const char *nfct_labels_get_path(void)
1536 {
1537  return __labels_get_path();
1538 }
1539 
1550 const char *nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
1551 {
1552  return __labelmap_get_name(m, bit);
1553 }
1554 
1563 int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)
1564 {
1565  return __labelmap_get_bit(m, name);
1566 }
1567 
1576 struct nfct_labelmap *nfct_labelmap_new(const char *mapfile)
1577 {
1578  return __labelmap_new(mapfile);
1579 }
1580 
1589 {
1590  __labelmap_destroy(map);
1591 }
1592 
1597 /*
1598  * \defgroup bitmask bitmask object
1599  *
1600  * @{
1601  */
1602 
1611 struct nfct_bitmask *nfct_bitmask_new(unsigned int max)
1612 {
1613  struct nfct_bitmask *b;
1614  unsigned int bytes, words;
1615 
1616  if (max > 0xffff)
1617  return NULL;
1618 
1619  words = DIV_ROUND_UP(max+1, 32);
1620  bytes = words * sizeof(b->bits[0]);
1621 
1622  b = malloc(sizeof(*b) + bytes);
1623  if (b) {
1624  memset(b->bits, 0, bytes);
1625  b->words = words;
1626  }
1627  return b;
1628 }
1629 
1630 /*
1631  * nfct_bitmask_clone - duplicate a bitmask object
1632  *
1633  * \param b pointer to the bitmask object to duplicate
1634  *
1635  * returns an identical copy of the bitmask.
1636  */
1637 struct nfct_bitmask *nfct_bitmask_clone(const struct nfct_bitmask *b)
1638 {
1639  unsigned int bytes = b->words * sizeof(b->bits[0]);
1640  struct nfct_bitmask *copy;
1641 
1642  bytes += sizeof(*b);
1643 
1644  copy = malloc(bytes);
1645  if (copy)
1646  memcpy(copy, b, bytes);
1647  return copy;
1648 }
1649 
1650 /*
1651  * nfct_bitmask_set_bit - set bit in the bitmask
1652  *
1653  * \param b pointer to the bitmask object
1654  * \param bit the bit to set
1655  */
1656 void nfct_bitmask_set_bit(struct nfct_bitmask *b, unsigned int bit)
1657 {
1658  unsigned int bits = b->words * 32;
1659  if (bit < bits)
1660  set_bit(bit, b->bits);
1661 }
1662 
1663 /*
1664  * nfct_bitmask_test_bit - test if a bit in the bitmask is set
1665  *
1666  * \param b pointer to the bitmask object
1667  * \param bit the bit to test
1668  *
1669  * returns 0 if the bit is not set.
1670  */
1671 int nfct_bitmask_test_bit(const struct nfct_bitmask *b, unsigned int bit)
1672 {
1673  unsigned int bits = b->words * 32;
1674  return bit < bits && test_bit(bit, b->bits);
1675 }
1676 
1677 /*
1678  * nfct_bitmask_unset_bit - unset bit in the bitmask
1679  *
1680  * \param b pointer to the bitmask object
1681  * \param bit the bit to clear
1682  */
1683 void nfct_bitmask_unset_bit(struct nfct_bitmask *b, unsigned int bit)
1684 {
1685  unsigned int bits = b->words * 32;
1686  if (bit < bits)
1687  unset_bit(bit, b->bits);
1688 }
1689 
1690 /*
1691  * nfct_bitmask_maxbit - return highest bit that may be set/unset
1692  *
1693  * \param b pointer to the bitmask object
1694  */
1695 unsigned int nfct_bitmask_maxbit(const struct nfct_bitmask *b)
1696 {
1697  return (b->words * 32) - 1;
1698 }
1699 
1700 /*
1701  * nfct_bitmask_destroy - destroy bitmask object
1702  *
1703  * \param b pointer to the bitmask object
1704  *
1705  * This function releases the memory that is used by the bitmask object.
1706  *
1707  * If you assign a bitmask object to a nf_conntrack object using
1708  * nfct_set_attr ATTR_CONNLABEL, then the ownership of the bitmask
1709  * object passes on to the nf_conntrack object. The nfct_bitmask object
1710  * will be destroyed when the nf_conntrack object is destroyed.
1711  */
1712 void nfct_bitmask_destroy(struct nfct_bitmask *b)
1713 {
1714  free(b);
1715 }
1716 
1717 /*
1718  * nfct_bitmask_clear - clear a bitmask object
1719  *
1720  * \param b pointer to the bitmask object to clear
1721  */
1722 void nfct_bitmask_clear(struct nfct_bitmask *b)
1723 {
1724  unsigned int bytes = b->words * sizeof(b->bits[0]);
1725  memset(b->bits, 0, bytes);
1726 }
1727 
1728 /*
1729  * nfct_bitmask_equal - compare two bitmask objects
1730  *
1731  * \param b1 pointer to a valid bitmask object
1732  * \param b2 pointer to a valid bitmask object
1733  *
1734  * If both bitmask object are equal, this function returns true, otherwise
1735  * false is returned.
1736  */
1737 bool nfct_bitmask_equal(const struct nfct_bitmask *b1, const struct nfct_bitmask *b2)
1738 {
1739  if (b1->words != b2->words)
1740  return false;
1741 
1742  return memcmp(b1->bits, b2->bits, b1->words * sizeof(b1->bits[0])) == 0;
1743 }
1744 
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)
Definition: conntrack/api.c:92
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)
Definition: conntrack/api.c:75
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)