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 
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_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 
901 int 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 
910 static 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 
951 int 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 
987 int 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 
1019 int 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 
1053 int nfct_catch(struct nfct_handle *h)
1054 {
1055  assert(h != NULL);
1056 
1057  return nfnl_catch(h->nfnlh);
1058 }
1059 
1109 int 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 
1137 int nfct_snprintf_labels(char *buf,
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 
1162 int 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 
1208 int 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 
1243 void 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 
1333 void 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 
1360 struct nfct_filter *nfct_filter_create(void)
1361 {
1362  return calloc(sizeof(struct nfct_filter), 1);
1363 }
1364 
1373 void nfct_filter_destroy(struct nfct_filter *filter)
1374 {
1375  assert(filter != NULL);
1376  free(filter);
1377  filter = NULL;
1378 }
1379 
1389 void 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 
1413 void 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 
1435 int 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 
1463 int 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 
1499 struct nfct_filter_dump *nfct_filter_dump_create(void)
1500 {
1501  return calloc(sizeof(struct nfct_filter_dump), 1);
1502 }
1503 
1510 void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
1511 {
1512  assert(filter != NULL);
1513  free(filter);
1514  filter = NULL;
1515 }
1516 
1523 void 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 
1545 void 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 
1568 const char *nfct_labels_get_path(void)
1569 {
1570  return __labels_get_path();
1571 }
1572 
1583 const char *nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
1584 {
1585  return __labelmap_get_name(m, bit);
1586 }
1587 
1596 int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)
1597 {
1598  return __labelmap_get_bit(m, name);
1599 }
1600 
1609 struct 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 
1644 struct 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  */
1670 struct 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  */
1689 void 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  */
1704 int 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  */
1716 void 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  */
1728 unsigned 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  */
1745 void 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  */
1755 void 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  */
1770 bool 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)
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)