libnetfilter_conntrack 1.1.0
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
29struct 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
46void nfexp_destroy(struct nf_expect *exp)
47{
48 assert(exp != NULL);
49 free(exp);
50 exp = NULL; /* bugtrap */
51}
52
57size_t nfexp_sizeof(const struct nf_expect *exp)
58{
59 assert(exp != NULL);
60 return sizeof(*exp);
61}
62
77size_t nfexp_maxsize(void)
78{
79 return sizeof(struct nf_expect);
80}
81
89struct 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
127int 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
158int 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
198void 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
232int 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
273void 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
309void 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
331void 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
344void 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
357void 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
372const 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
399uint8_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
415uint16_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
431uint32_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
446int 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
466int 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
505int 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 memset(req, 0, size);
517
518 return __build_expect(req, size, type, flags, exp);
519}
520
521static void nfexp_fill_hdr(struct nfnlhdr *req, uint16_t type, uint16_t flags,
522 uint8_t l3num, uint8_t version)
523{
524 char *buf = (char *)&req->nlh;
525 struct nlmsghdr *nlh;
526 struct nfgenmsg *nfh;
527
528 nlh = mnl_nlmsg_put_header(buf);
529 nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK_EXP << 8) | type;
530 nlh->nlmsg_flags = NLM_F_REQUEST | flags;
531 nlh->nlmsg_seq = 0;
532
533 nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
534 nfh->nfgen_family = l3num;
535 nfh->version = version;
536 nfh->res_id = 0;
537}
538
539static int
540__build_query_exp(const enum nf_conntrack_query qt,
541 const void *data, void *buffer, unsigned int size)
542{
543 struct nfnlhdr *req = buffer;
544 const uint8_t *family = data;
545
546 assert(data != NULL);
547 assert(req != NULL);
548
549 memset(buffer, 0, size);
550
551 switch(qt) {
552 case NFCT_Q_CREATE:
553 __build_expect(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(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(req, size, IPCTNL_MSG_EXP_GET, NLM_F_REQUEST|NLM_F_ACK, data);
560 break;
561 case NFCT_Q_DESTROY:
562 __build_expect(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
609int 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(qt, data, buffer, size);
616}
617
618static 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
659int 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
695int 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(qt, data, &u.req, size) == -1)
709 return -1;
710
711 return nfnl_query(h->nfnlh, &u.req.nlh);
712}
713
727int 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(qt, data, &u.req, size) == -1)
741 return -1;
742
743 return nfnl_send(h->nfnlh, &u.req.nlh);
744}
745
760int nfexp_catch(struct nfct_handle *h)
761{
762 assert(h != NULL);
763
764 return nfnl_catch(h->nfnlh);
765}
766
802int 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_new(void)
Definition expect/api.c:29
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
const void * nfexp_get_attr(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition expect/api.c:372
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
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
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
struct nf_expect * nfexp_clone(const struct nf_expect *exp)
Definition expect/api.c:89
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