libnetfilter_conntrack  1.0.9
expect/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 <string.h> /* for memset */
12 #include <errno.h>
13 #include <assert.h>
14 #include <libmnl/libmnl.h>
15 
16 #include "internal/internal.h"
17 
29 struct nf_expect *nfexp_new(void)
30 {
31  struct nf_expect *exp;
32 
33  exp = malloc(sizeof(struct nf_expect));
34  if (!exp)
35  return NULL;
36 
37  memset(exp, 0, sizeof(struct nf_expect));
38 
39  return exp;
40 }
41 
46 void nfexp_destroy(struct nf_expect *exp)
47 {
48  assert(exp != NULL);
49  free(exp);
50  exp = NULL; /* bugtrap */
51 }
52 
57 size_t nfexp_sizeof(const struct nf_expect *exp)
58 {
59  assert(exp != NULL);
60  return sizeof(*exp);
61 }
62 
77 size_t nfexp_maxsize(void)
78 {
79  return sizeof(struct nf_expect);
80 }
81 
89 struct nf_expect *nfexp_clone(const struct nf_expect *exp)
90 {
91  struct nf_expect *clone;
92 
93  assert(exp != NULL);
94 
95  if ((clone = nfexp_new()) == NULL)
96  return NULL;
97  memcpy(clone, exp, sizeof(*exp));
98 
99  return clone;
100 }
101 
127 int nfexp_cmp(const struct nf_expect *exp1, const struct nf_expect *exp2,
128  unsigned int flags)
129 {
130  assert(exp1 != NULL);
131  assert(exp2 != NULL);
132 
133  return __cmp_expect(exp1, exp2, flags);
134 }
135 
158 int nfexp_callback_register(struct nfct_handle *h,
159  enum nf_conntrack_msg_type type,
160  int (*cb)(enum nf_conntrack_msg_type type,
161  struct nf_expect *exp,
162  void *data),
163  void *data)
164 {
165  struct __data_container *container;
166 
167  assert(h != NULL);
168 
169  container = malloc(sizeof(struct __data_container));
170  if (!container)
171  return -1;
172  memset(container, 0, sizeof(struct __data_container));
173 
174  h->expect_cb = cb;
175  container->h = h;
176  container->type = type;
177  container->data = data;
178 
179  h->nfnl_cb_exp.call = __callback;
180  h->nfnl_cb_exp.data = container;
181  h->nfnl_cb_exp.attr_count = CTA_EXPECT_MAX;
182 
183  nfnl_callback_register(h->nfnlssh_exp,
184  IPCTNL_MSG_EXP_NEW,
185  &h->nfnl_cb_exp);
186 
187  nfnl_callback_register(h->nfnlssh_exp,
188  IPCTNL_MSG_EXP_DELETE,
189  &h->nfnl_cb_exp);
190 
191  return 0;
192 }
193 
198 void nfexp_callback_unregister(struct nfct_handle *h)
199 {
200  assert(h != NULL);
201 
202  nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_NEW);
203  nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_DELETE);
204 
205  h->expect_cb = NULL;
206  free(h->nfnl_cb_exp.data);
207 
208  h->nfnl_cb_exp.call = NULL;
209  h->nfnl_cb_exp.data = NULL;
210  h->nfnl_cb_exp.attr_count = 0;
211 }
212 
232 int nfexp_callback_register2(struct nfct_handle *h,
233  enum nf_conntrack_msg_type type,
234  int (*cb)(const struct nlmsghdr *nlh,
235  enum nf_conntrack_msg_type type,
236  struct nf_expect *exp,
237  void *data),
238  void *data)
239 {
240  struct __data_container *container;
241 
242  assert(h != NULL);
243 
244  container = malloc(sizeof(struct __data_container));
245  if (!container)
246  return -1;
247  memset(container, 0, sizeof(struct __data_container));
248 
249  h->expect_cb2 = cb;
250  container->h = h;
251  container->type = type;
252  container->data = data;
253 
254  h->nfnl_cb_exp.call = __callback;
255  h->nfnl_cb_exp.data = container;
256  h->nfnl_cb_exp.attr_count = CTA_EXPECT_MAX;
257 
258  nfnl_callback_register(h->nfnlssh_exp,
259  IPCTNL_MSG_EXP_NEW,
260  &h->nfnl_cb_exp);
261 
262  nfnl_callback_register(h->nfnlssh_exp,
263  IPCTNL_MSG_EXP_DELETE,
264  &h->nfnl_cb_exp);
265 
266  return 0;
267 }
268 
273 void nfexp_callback_unregister2(struct nfct_handle *h)
274 {
275  assert(h != NULL);
276 
277  nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_NEW);
278  nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_DELETE);
279 
280  h->expect_cb2 = NULL;
281  free(h->nfnl_cb_exp.data);
282 
283  h->nfnl_cb_exp.call = NULL;
284  h->nfnl_cb_exp.data = NULL;
285  h->nfnl_cb_exp.attr_count = 0;
286 }
287 
309 void nfexp_set_attr(struct nf_expect *exp,
310  const enum nf_expect_attr type,
311  const void *value)
312 {
313  assert(exp != NULL);
314  assert(value != NULL);
315 
316  if (type >= ATTR_EXP_MAX)
317  return;
318 
319  if (set_exp_attr_array[type]) {
320  set_exp_attr_array[type](exp, value);
321  set_bit(type, exp->set);
322  }
323 }
324 
331 void nfexp_set_attr_u8(struct nf_expect *exp,
332  const enum nf_expect_attr type,
333  uint8_t value)
334 {
335  nfexp_set_attr(exp, type, &value);
336 }
337 
344 void nfexp_set_attr_u16(struct nf_expect *exp,
345  const enum nf_expect_attr type,
346  uint16_t value)
347 {
348  nfexp_set_attr(exp, type, &value);
349 }
350 
357 void nfexp_set_attr_u32(struct nf_expect *exp,
358  const enum nf_expect_attr type,
359  uint32_t value)
360 {
361  nfexp_set_attr(exp, type, &value);
362 }
363 
372 const void *nfexp_get_attr(const struct nf_expect *exp,
373  const enum nf_expect_attr type)
374 {
375  assert(exp != NULL);
376 
377  if (type >= ATTR_EXP_MAX) {
378  errno = EINVAL;
379  return NULL;
380  }
381 
382  if (!test_bit(type, exp->set)) {
383  errno = ENODATA;
384  return NULL;
385  }
386 
387  return get_exp_attr_array[type](exp);
388 }
389 
399 uint8_t nfexp_get_attr_u8(const struct nf_expect *exp,
400  const enum nf_expect_attr type)
401 {
402  const uint8_t *ret = nfexp_get_attr(exp, type);
403  return ret == NULL ? 0 : *ret;
404 }
405 
415 uint16_t nfexp_get_attr_u16(const struct nf_expect *exp,
416  const enum nf_expect_attr type)
417 {
418  const uint16_t *ret = nfexp_get_attr(exp, type);
419  return ret == NULL ? 0 : *ret;
420 }
421 
431 uint32_t nfexp_get_attr_u32(const struct nf_expect *exp,
432  const enum nf_expect_attr type)
433 {
434  const uint32_t *ret = nfexp_get_attr(exp, type);
435  return ret == NULL ? 0 : *ret;
436 }
437 
446 int nfexp_attr_is_set(const struct nf_expect *exp,
447  const enum nf_expect_attr type)
448 {
449  assert(exp != NULL);
450 
451  if (type >= ATTR_EXP_MAX) {
452  errno = EINVAL;
453  return -1;
454  }
455  return test_bit(type, exp->set);
456 }
457 
466 int nfexp_attr_unset(struct nf_expect *exp,
467  const enum nf_expect_attr type)
468 {
469  assert(exp != NULL);
470 
471  if (type >= ATTR_EXP_MAX) {
472  errno = EINVAL;
473  return -1;
474  }
475  unset_bit(type, exp->set);
476 
477  return 0;
478 }
479 
505 int nfexp_build_expect(struct nfnl_subsys_handle *ssh,
506  void *req,
507  size_t size,
508  uint16_t type,
509  uint16_t flags,
510  const struct nf_expect *exp)
511 {
512  assert(ssh != NULL);
513  assert(req != NULL);
514  assert(exp != NULL);
515 
516  return __build_expect(ssh, req, size, type, flags, exp);
517 }
518 
519 static void nfexp_fill_hdr(struct nfnlhdr *req, uint16_t type, uint16_t flags,
520  uint8_t l3num, uint8_t version)
521 {
522  char *buf = (char *)&req->nlh;
523  struct nlmsghdr *nlh;
524  struct nfgenmsg *nfh;
525 
526  nlh = mnl_nlmsg_put_header(buf);
527  nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK_EXP << 8) | type;
528  nlh->nlmsg_flags = NLM_F_REQUEST | flags;
529  nlh->nlmsg_seq = 0;
530 
531  nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
532  nfh->nfgen_family = l3num;
533  nfh->version = version;
534  nfh->res_id = 0;
535 }
536 
537 static int
538 __build_query_exp(struct nfnl_subsys_handle *ssh,
539  const enum nf_conntrack_query qt,
540  const void *data, void *buffer, unsigned int size)
541 {
542  struct nfnlhdr *req = buffer;
543  const uint8_t *family = data;
544 
545  assert(ssh != NULL);
546  assert(data != NULL);
547  assert(req != NULL);
548 
549  memset(req, 0, size);
550 
551  switch(qt) {
552  case NFCT_Q_CREATE:
553  __build_expect(ssh, req, size, IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
554  break;
555  case NFCT_Q_CREATE_UPDATE:
556  __build_expect(ssh, req, size, IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data);
557  break;
558  case NFCT_Q_GET:
559  __build_expect(ssh, req, size, IPCTNL_MSG_EXP_GET, NLM_F_REQUEST|NLM_F_ACK, data);
560  break;
561  case NFCT_Q_DESTROY:
562  __build_expect(ssh, req, size, IPCTNL_MSG_EXP_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
563  break;
564  case NFCT_Q_FLUSH:
565  nfexp_fill_hdr(req, IPCTNL_MSG_EXP_DELETE, NLM_F_ACK, *family,
566  NFNETLINK_V0);
567  break;
568  case NFCT_Q_DUMP:
569  nfexp_fill_hdr(req, IPCTNL_MSG_EXP_GET, NLM_F_DUMP, *family,
570  NFNETLINK_V0);
571  break;
572  default:
573  errno = ENOTSUP;
574  return -1;
575  }
576  return 1;
577 }
578 
609 int nfexp_build_query(struct nfnl_subsys_handle *ssh,
610  const enum nf_conntrack_query qt,
611  const void *data,
612  void *buffer,
613  unsigned int size)
614 {
615  return __build_query_exp(ssh, qt, data, buffer, size);
616 }
617 
618 static int __parse_expect_message_type(const struct nlmsghdr *nlh)
619 {
620  uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
621  uint16_t flags = nlh->nlmsg_flags;
622  int ret = NFCT_T_UNKNOWN;
623 
624  if (type == IPCTNL_MSG_EXP_NEW) {
625  if (flags & (NLM_F_CREATE|NLM_F_EXCL))
626  ret = NFCT_T_NEW;
627  else
628  ret = NFCT_T_UPDATE;
629  } else if (type == IPCTNL_MSG_EXP_DELETE)
630  ret = NFCT_T_DESTROY;
631 
632  return ret;
633 }
634 
659 int nfexp_parse_expect(enum nf_conntrack_msg_type type,
660  const struct nlmsghdr *nlh,
661  struct nf_expect *exp)
662 {
663  unsigned int flags;
664 
665  assert(nlh != NULL);
666  assert(exp != NULL);
667 
668  flags = __parse_expect_message_type(nlh);
669  if (!(flags & type))
670  return 0;
671 
672  nfexp_nlmsg_parse(nlh, exp);
673 
674  return flags;
675 }
676 
695 int nfexp_query(struct nfct_handle *h,
696  const enum nf_conntrack_query qt,
697  const void *data)
698 {
699  const size_t size = 4096; /* enough for now */
700  union {
701  char buffer[size];
702  struct nfnlhdr req;
703  } u;
704 
705  assert(h != NULL);
706  assert(data != NULL);
707 
708  if (__build_query_exp(h->nfnlssh_exp, qt, data, &u.req, size) == -1)
709  return -1;
710 
711  return nfnl_query(h->nfnlh, &u.req.nlh);
712 }
713 
727 int nfexp_send(struct nfct_handle *h,
728  const enum nf_conntrack_query qt,
729  const void *data)
730 {
731  const size_t size = 4096; /* enough for now */
732  union {
733  char buffer[size];
734  struct nfnlhdr req;
735  } u;
736 
737  assert(h != NULL);
738  assert(data != NULL);
739 
740  if (__build_query_exp(h->nfnlssh_exp, qt, data, &u.req, size) == -1)
741  return -1;
742 
743  return nfnl_send(h->nfnlh, &u.req.nlh);
744 }
745 
760 int nfexp_catch(struct nfct_handle *h)
761 {
762  assert(h != NULL);
763 
764  return nfnl_catch(h->nfnlh);
765 }
766 
802 int nfexp_snprintf(char *buf,
803  unsigned int size,
804  const struct nf_expect *exp,
805  unsigned int msg_type,
806  unsigned int out_type,
807  unsigned int flags)
808 {
809  assert(buf != NULL);
810  assert(size > 0);
811  assert(exp != NULL);
812 
813  return __snprintf_expect(buf, size, exp, msg_type, out_type, flags);
814 }
815 
void nfexp_callback_unregister(struct nfct_handle *h)
Definition: expect/api.c:198
void nfexp_callback_unregister2(struct nfct_handle *h)
Definition: expect/api.c:273
int nfexp_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_expect *exp, void *data), void *data)
Definition: expect/api.c:232
int nfexp_callback_register(struct nfct_handle *h, enum nf_conntrack_msg_type type, int(*cb)(enum nf_conntrack_msg_type type, struct nf_expect *exp, void *data), void *data)
Definition: expect/api.c:158
int nfexp_catch(struct nfct_handle *h)
Definition: expect/api.c:760
int nfexp_send(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
Definition: expect/api.c:727
int nfexp_query(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
Definition: expect/api.c:695
void nfexp_set_attr_u32(struct nf_expect *exp, const enum nf_expect_attr type, uint32_t value)
Definition: expect/api.c:357
struct nf_expect * nfexp_clone(const struct nf_expect *exp)
Definition: expect/api.c:89
uint32_t nfexp_get_attr_u32(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:431
size_t nfexp_sizeof(const struct nf_expect *exp)
Definition: expect/api.c:57
void nfexp_set_attr_u16(struct nf_expect *exp, const enum nf_expect_attr type, uint16_t value)
Definition: expect/api.c:344
void nfexp_set_attr(struct nf_expect *exp, const enum nf_expect_attr type, const void *value)
Definition: expect/api.c:309
int nfexp_cmp(const struct nf_expect *exp1, const struct nf_expect *exp2, unsigned int flags)
Definition: expect/api.c:127
uint16_t nfexp_get_attr_u16(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:415
void nfexp_set_attr_u8(struct nf_expect *exp, const enum nf_expect_attr type, uint8_t value)
Definition: expect/api.c:331
const void * nfexp_get_attr(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:372
uint8_t nfexp_get_attr_u8(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:399
int nfexp_snprintf(char *buf, unsigned int size, const struct nf_expect *exp, unsigned int msg_type, unsigned int out_type, unsigned int flags)
Definition: expect/api.c:802
struct nf_expect * nfexp_new(void)
Definition: expect/api.c:29
void nfexp_destroy(struct nf_expect *exp)
Definition: expect/api.c:46
int nfexp_attr_unset(struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:466
int nfexp_attr_is_set(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:446
size_t nfexp_maxsize(void)
Definition: expect/api.c:77
int nfexp_build_query(struct nfnl_subsys_handle *ssh, const enum nf_conntrack_query qt, const void *data, void *buffer, unsigned int size)
Definition: expect/api.c:609
int nfexp_build_expect(struct nfnl_subsys_handle *ssh, void *req, size_t size, uint16_t type, uint16_t flags, const struct nf_expect *exp)
Definition: expect/api.c:505
int nfexp_parse_expect(enum nf_conntrack_msg_type type, const struct nlmsghdr *nlh, struct nf_expect *exp)
Definition: expect/api.c:659