libnetfilter_conntrack  1.0.6
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 
15 #include "internal/internal.h"
16 
28 struct nf_expect *nfexp_new(void)
29 {
30  struct nf_expect *exp;
31 
32  exp = malloc(sizeof(struct nf_expect));
33  if (!exp)
34  return NULL;
35 
36  memset(exp, 0, sizeof(struct nf_expect));
37 
38  return exp;
39 }
40 
45 void nfexp_destroy(struct nf_expect *exp)
46 {
47  assert(exp != NULL);
48  free(exp);
49  exp = NULL; /* bugtrap */
50 }
51 
56 size_t nfexp_sizeof(const struct nf_expect *exp)
57 {
58  assert(exp != NULL);
59  return sizeof(*exp);
60 }
61 
76 size_t nfexp_maxsize(void)
77 {
78  return sizeof(struct nf_expect);
79 }
80 
88 struct nf_expect *nfexp_clone(const struct nf_expect *exp)
89 {
90  struct nf_expect *clone;
91 
92  assert(exp != NULL);
93 
94  if ((clone = nfexp_new()) == NULL)
95  return NULL;
96  memcpy(clone, exp, sizeof(*exp));
97 
98  return clone;
99 }
100 
126 int nfexp_cmp(const struct nf_expect *exp1, const struct nf_expect *exp2,
127  unsigned int flags)
128 {
129  assert(exp1 != NULL);
130  assert(exp2 != NULL);
131 
132  return __cmp_expect(exp1, exp2, flags);
133 }
134 
157 int nfexp_callback_register(struct nfct_handle *h,
158  enum nf_conntrack_msg_type type,
159  int (*cb)(enum nf_conntrack_msg_type type,
160  struct nf_expect *exp,
161  void *data),
162  void *data)
163 {
164  struct __data_container *container;
165 
166  assert(h != NULL);
167 
168  container = malloc(sizeof(struct __data_container));
169  if (!container)
170  return -1;
171  memset(container, 0, sizeof(struct __data_container));
172 
173  h->expect_cb = cb;
174  container->h = h;
175  container->type = type;
176  container->data = data;
177 
178  h->nfnl_cb_exp.call = __callback;
179  h->nfnl_cb_exp.data = container;
180  h->nfnl_cb_exp.attr_count = CTA_EXPECT_MAX;
181 
182  nfnl_callback_register(h->nfnlssh_exp,
183  IPCTNL_MSG_EXP_NEW,
184  &h->nfnl_cb_exp);
185 
186  nfnl_callback_register(h->nfnlssh_exp,
187  IPCTNL_MSG_EXP_DELETE,
188  &h->nfnl_cb_exp);
189 
190  return 0;
191 }
192 
197 void nfexp_callback_unregister(struct nfct_handle *h)
198 {
199  assert(h != NULL);
200 
201  nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_NEW);
202  nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_DELETE);
203 
204  h->expect_cb = NULL;
205  free(h->nfnl_cb_exp.data);
206 
207  h->nfnl_cb_exp.call = NULL;
208  h->nfnl_cb_exp.data = NULL;
209  h->nfnl_cb_exp.attr_count = 0;
210 }
211 
231 int nfexp_callback_register2(struct nfct_handle *h,
232  enum nf_conntrack_msg_type type,
233  int (*cb)(const struct nlmsghdr *nlh,
234  enum nf_conntrack_msg_type type,
235  struct nf_expect *exp,
236  void *data),
237  void *data)
238 {
239  struct __data_container *container;
240 
241  assert(h != NULL);
242 
243  container = malloc(sizeof(struct __data_container));
244  if (!container)
245  return -1;
246  memset(container, 0, sizeof(struct __data_container));
247 
248  h->expect_cb2 = cb;
249  container->h = h;
250  container->type = type;
251  container->data = data;
252 
253  h->nfnl_cb_exp.call = __callback;
254  h->nfnl_cb_exp.data = container;
255  h->nfnl_cb_exp.attr_count = CTA_EXPECT_MAX;
256 
257  nfnl_callback_register(h->nfnlssh_exp,
258  IPCTNL_MSG_EXP_NEW,
259  &h->nfnl_cb_exp);
260 
261  nfnl_callback_register(h->nfnlssh_exp,
262  IPCTNL_MSG_EXP_DELETE,
263  &h->nfnl_cb_exp);
264 
265  return 0;
266 }
267 
272 void nfexp_callback_unregister2(struct nfct_handle *h)
273 {
274  assert(h != NULL);
275 
276  nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_NEW);
277  nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_DELETE);
278 
279  h->expect_cb2 = NULL;
280  free(h->nfnl_cb_exp.data);
281 
282  h->nfnl_cb_exp.call = NULL;
283  h->nfnl_cb_exp.data = NULL;
284  h->nfnl_cb_exp.attr_count = 0;
285 }
286 
308 void nfexp_set_attr(struct nf_expect *exp,
309  const enum nf_expect_attr type,
310  const void *value)
311 {
312  assert(exp != NULL);
313  assert(value != NULL);
314 
315  if (type >= ATTR_EXP_MAX)
316  return;
317 
318  if (set_exp_attr_array[type]) {
319  set_exp_attr_array[type](exp, value);
320  set_bit(type, exp->set);
321  }
322 }
323 
330 void nfexp_set_attr_u8(struct nf_expect *exp,
331  const enum nf_expect_attr type,
332  uint8_t value)
333 {
334  nfexp_set_attr(exp, type, &value);
335 }
336 
343 void nfexp_set_attr_u16(struct nf_expect *exp,
344  const enum nf_expect_attr type,
345  uint16_t value)
346 {
347  nfexp_set_attr(exp, type, &value);
348 }
349 
356 void nfexp_set_attr_u32(struct nf_expect *exp,
357  const enum nf_expect_attr type,
358  uint32_t value)
359 {
360  nfexp_set_attr(exp, type, &value);
361 }
362 
371 const void *nfexp_get_attr(const struct nf_expect *exp,
372  const enum nf_expect_attr type)
373 {
374  assert(exp != NULL);
375 
376  if (type >= ATTR_EXP_MAX) {
377  errno = EINVAL;
378  return NULL;
379  }
380 
381  if (!test_bit(type, exp->set)) {
382  errno = ENODATA;
383  return NULL;
384  }
385 
386  return get_exp_attr_array[type](exp);
387 }
388 
398 uint8_t nfexp_get_attr_u8(const struct nf_expect *exp,
399  const enum nf_expect_attr type)
400 {
401  const uint8_t *ret = nfexp_get_attr(exp, type);
402  return ret == NULL ? 0 : *ret;
403 }
404 
414 uint16_t nfexp_get_attr_u16(const struct nf_expect *exp,
415  const enum nf_expect_attr type)
416 {
417  const uint16_t *ret = nfexp_get_attr(exp, type);
418  return ret == NULL ? 0 : *ret;
419 }
420 
430 uint32_t nfexp_get_attr_u32(const struct nf_expect *exp,
431  const enum nf_expect_attr type)
432 {
433  const uint32_t *ret = nfexp_get_attr(exp, type);
434  return ret == NULL ? 0 : *ret;
435 }
436 
445 int nfexp_attr_is_set(const struct nf_expect *exp,
446  const enum nf_expect_attr type)
447 {
448  assert(exp != NULL);
449 
450  if (type >= ATTR_EXP_MAX) {
451  errno = EINVAL;
452  return -1;
453  }
454  return test_bit(type, exp->set);
455 }
456 
465 int nfexp_attr_unset(struct nf_expect *exp,
466  const enum nf_expect_attr type)
467 {
468  assert(exp != NULL);
469 
470  if (type >= ATTR_EXP_MAX) {
471  errno = EINVAL;
472  return -1;
473  }
474  unset_bit(type, exp->set);
475 
476  return 0;
477 }
478 
504 int nfexp_build_expect(struct nfnl_subsys_handle *ssh,
505  void *req,
506  size_t size,
507  uint16_t type,
508  uint16_t flags,
509  const struct nf_expect *exp)
510 {
511  assert(ssh != NULL);
512  assert(req != NULL);
513  assert(exp != NULL);
514 
515  return __build_expect(ssh, req, size, type, flags, exp);
516 }
517 
518 static int
519 __build_query_exp(struct nfnl_subsys_handle *ssh,
520  const enum nf_conntrack_query qt,
521  const void *data, void *buffer, unsigned int size)
522 {
523  struct nfnlhdr *req = buffer;
524  const uint8_t *family = data;
525 
526  assert(ssh != NULL);
527  assert(data != NULL);
528  assert(req != NULL);
529 
530  memset(req, 0, size);
531 
532  switch(qt) {
533  case NFCT_Q_CREATE:
534  __build_expect(ssh, req, size, IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
535  break;
536  case NFCT_Q_CREATE_UPDATE:
537  __build_expect(ssh, req, size, IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data);
538  break;
539  case NFCT_Q_GET:
540  __build_expect(ssh, req, size, IPCTNL_MSG_EXP_GET, NLM_F_REQUEST|NLM_F_ACK, data);
541  break;
542  case NFCT_Q_DESTROY:
543  __build_expect(ssh, req, size, IPCTNL_MSG_EXP_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
544  break;
545  case NFCT_Q_FLUSH:
546  nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_EXP_DELETE, NLM_F_REQUEST|NLM_F_ACK);
547  break;
548  case NFCT_Q_DUMP:
549  nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_EXP_GET, NLM_F_REQUEST|NLM_F_DUMP);
550  break;
551  default:
552  errno = ENOTSUP;
553  return -1;
554  }
555  return 1;
556 }
557 
588 int nfexp_build_query(struct nfnl_subsys_handle *ssh,
589  const enum nf_conntrack_query qt,
590  const void *data,
591  void *buffer,
592  unsigned int size)
593 {
594  return __build_query_exp(ssh, qt, data, buffer, size);
595 }
596 
621 int nfexp_parse_expect(enum nf_conntrack_msg_type type,
622  const struct nlmsghdr *nlh,
623  struct nf_expect *exp)
624 {
625  unsigned int flags;
626  int len = nlh->nlmsg_len;
627  struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
628  struct nfattr *cda[CTA_EXPECT_MAX];
629 
630  assert(nlh != NULL);
631  assert(exp != NULL);
632 
633  len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
634  if (len < 0) {
635  errno = EINVAL;
636  return NFCT_T_ERROR;
637  }
638 
639  flags = __parse_expect_message_type(nlh);
640  if (!(flags & type))
641  return 0;
642 
643  nfnl_parse_attr(cda, CTA_EXPECT_MAX, NFA_DATA(nfhdr), len);
644 
645  __parse_expect(nlh, cda, exp);
646 
647  return flags;
648 }
649 
668 int nfexp_query(struct nfct_handle *h,
669  const enum nf_conntrack_query qt,
670  const void *data)
671 {
672  const size_t size = 4096; /* enough for now */
673  union {
674  char buffer[size];
675  struct nfnlhdr req;
676  } u;
677 
678  assert(h != NULL);
679  assert(data != NULL);
680 
681  if (__build_query_exp(h->nfnlssh_exp, qt, data, &u.req, size) == -1)
682  return -1;
683 
684  return nfnl_query(h->nfnlh, &u.req.nlh);
685 }
686 
700 int nfexp_send(struct nfct_handle *h,
701  const enum nf_conntrack_query qt,
702  const void *data)
703 {
704  const size_t size = 4096; /* enough for now */
705  union {
706  char buffer[size];
707  struct nfnlhdr req;
708  } u;
709 
710  assert(h != NULL);
711  assert(data != NULL);
712 
713  if (__build_query_exp(h->nfnlssh_exp, qt, data, &u.req, size) == -1)
714  return -1;
715 
716  return nfnl_send(h->nfnlh, &u.req.nlh);
717 }
718 
733 int nfexp_catch(struct nfct_handle *h)
734 {
735  assert(h != NULL);
736 
737  return nfnl_catch(h->nfnlh);
738 }
739 
774 int nfexp_snprintf(char *buf,
775  unsigned int size,
776  const struct nf_expect *exp,
777  unsigned int msg_type,
778  unsigned int out_type,
779  unsigned int flags)
780 {
781  assert(buf != NULL);
782  assert(size > 0);
783  assert(exp != NULL);
784 
785  return __snprintf_expect(buf, size, exp, msg_type, out_type, flags);
786 }
787 
void nfexp_set_attr(struct nf_expect *exp, const enum nf_expect_attr type, const void *value)
Definition: expect/api.c:308
size_t nfexp_maxsize(void)
Definition: expect/api.c:76
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:231
void nfexp_set_attr_u32(struct nf_expect *exp, const enum nf_expect_attr type, uint32_t value)
Definition: expect/api.c:356
uint32_t nfexp_get_attr_u32(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:430
void nfexp_callback_unregister2(struct nfct_handle *h)
Definition: expect/api.c:272
void nfexp_set_attr_u16(struct nf_expect *exp, const enum nf_expect_attr type, uint16_t value)
Definition: expect/api.c:343
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:504
int nfexp_query(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
Definition: expect/api.c:668
struct nf_expect * nfexp_clone(const struct nf_expect *exp)
Definition: expect/api.c:88
int nfexp_cmp(const struct nf_expect *exp1, const struct nf_expect *exp2, unsigned int flags)
Definition: expect/api.c:126
int nfexp_send(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
Definition: expect/api.c:700
uint16_t nfexp_get_attr_u16(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:414
struct nf_expect * nfexp_new(void)
Definition: expect/api.c:28
int nfexp_attr_unset(struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:465
int nfexp_parse_expect(enum nf_conntrack_msg_type type, const struct nlmsghdr *nlh, struct nf_expect *exp)
Definition: expect/api.c:621
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:774
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:588
void nfexp_set_attr_u8(struct nf_expect *exp, const enum nf_expect_attr type, uint8_t value)
Definition: expect/api.c:330
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:157
int nfexp_attr_is_set(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:445
int nfexp_catch(struct nfct_handle *h)
Definition: expect/api.c:733
uint8_t nfexp_get_attr_u8(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:398
void nfexp_callback_unregister(struct nfct_handle *h)
Definition: expect/api.c:197
size_t nfexp_sizeof(const struct nf_expect *exp)
Definition: expect/api.c:56
void nfexp_destroy(struct nf_expect *exp)
Definition: expect/api.c:45
const void * nfexp_get_attr(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition: expect/api.c:371