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
17 /**
18 * \defgroup exp Expect object handling
19 * @{
20 */
21
22 /**
23 * nfexp_new - allocate a new expectation
24 *
25 * In case of success, this function returns a valid pointer to a memory blob,
26 * otherwise NULL is returned and errno is set appropiately.
27 */
nfexp_new(void)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
41 /**
42 * nfexp_destroy - release an expectation object
43 * \param exp pointer to the expectation object
44 */
nfexp_destroy(struct nf_expect * exp)45 void nfexp_destroy(struct nf_expect *exp)
46 {
47 assert(exp != NULL);
48 free(exp);
49 exp = NULL; /* bugtrap */
50 }
51
52 /**
53 * nfexp_sizeof - return the size in bytes of a certain expect object
54 * \param exp pointer to the expect object
55 */
nfexp_sizeof(const struct nf_expect * exp)56 size_t nfexp_sizeof(const struct nf_expect *exp)
57 {
58 assert(exp != NULL);
59 return sizeof(*exp);
60 }
61
62 /**
63 * nfexp_maxsize - return the maximum size in bytes of a expect object
64 *
65 * Use this function if you want to allocate a expect object in the stack
66 * instead of the heap. For example:
67 *
68 * char buf[nfexp_maxsize()];
69 * struct nf_expect *exp = (struct nf_expect *) buf;
70 * memset(exp, 0, nfexp_maxsize());
71 *
72 * Note: As for now this function returns the same size that nfexp_sizeof(exp)
73 * does although _this could change in the future_. Therefore, do not assume
74 * that nfexp_sizeof(exp) == nfexp_maxsize().
75 */
nfexp_maxsize(void)76 size_t nfexp_maxsize(void)
77 {
78 return sizeof(struct nf_expect);
79 }
80
81 /**
82 * nfexp_clone - clone a expectation object
83 * \param exp pointer to a valid expectation object
84 *
85 * On error, NULL is returned and errno is appropiately set. Otherwise,
86 * a valid pointer to the clone expect is returned.
87 */
nfexp_clone(const struct nf_expect * exp)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
101 /**
102 * nfexp_cmp - compare two expectation objects
103 * \param exp1 pointer to a valid expectation object
104 * \param exp2 pointer to a valid expectation object
105 * \param flags flags
106 *
107 * This function only compare attribute set in both objects, by default
108 * the comparison is not strict, ie. if a certain attribute is not set in one
109 * of the objects, then such attribute is not used in the comparison.
110 * If you want more strict comparisons, you can use the appropriate flags
111 * to modify this behaviour (see NFCT_CMP_STRICT and NFCT_CMP_MASK).
112 *
113 * The available flags are:
114 * - NFCT_CMP_STRICT: the compared objects must have the same attributes
115 * and the same values, otherwise it returns that the objects are
116 * different.
117 * - NFCT_CMP_MASK: the first object is used as mask, this means that
118 * if an attribute is present in exp1 but not in exp2, this function
119 * returns that the objects are different.
120 *
121 * Other existing flags that are used by nfct_cmp() are ignored.
122 *
123 * If both conntrack object are equal, this function returns 1, otherwise
124 * 0 is returned.
125 */
nfexp_cmp(const struct nf_expect * exp1,const struct nf_expect * exp2,unsigned int flags)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
135 /**
136 * @}
137 */
138
139 /**
140 * \defgroup LibrarySetup Library setup
141 * @{
142 */
143
144 /**
145 * nfexp_callback_register - register a callback
146 * \param h library handler
147 * \param cb callback used to process expect received
148 * \param data data used by the callback, if any.
149 *
150 * This function register a callback to handle the expect received,
151 * in case of error -1 is returned and errno is set appropiately, otherwise
152 * 0 is returned.
153 *
154 * Note that the data parameter is optional, if you do not want to pass any
155 * data to your callback, then use NULL.
156 */
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)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
193 /**
194 * nfexp_callback_unregister - unregister a callback
195 * \param h library handler
196 */
nfexp_callback_unregister(struct nfct_handle * h)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
212 /**
213 * nfexp_callback_register2 - register a callback
214 * \param h library handler
215 * \param cb callback used to process expect received
216 * \param data data used by the callback, if any.
217 *
218 * This function register a callback to handle the expect received,
219 * in case of error -1 is returned and errno is set appropiately, otherwise
220 * 0 is returned.
221 *
222 * Note that the data parameter is optional, if you do not want to pass any
223 * data to your callback, then use NULL.
224 *
225 * NOTICE: The difference with nfexp_callback_register() is that this function
226 * uses the new callback interface that includes the Netlink header.
227 *
228 * WARNING: Don't mix nfexp_callback_register() and nfexp_callback_register2()
229 * calls, use only once at a time.
230 */
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)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
268 /**
269 * nfexp_callback_unregister2 - unregister a callback
270 * \param h library handler
271 */
nfexp_callback_unregister2(struct nfct_handle * h)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
287 /**
288 * @}
289 */
290
291 /**
292 * \defgroup exp Expect object handling
293 * @{
294 */
295
296 /**
297 * nfexp_set_attr - set the value of a certain expect attribute
298 * \param exp pointer to a valid expect
299 * \param type attribute type
300 * \param value pointer to the attribute value
301 *
302 * Note that certain attributes are unsettable:
303 * - ATTR_EXP_USE
304 * - ATTR_EXP_ID
305 * - ATTR_EXP_*_COUNTER_*
306 * The call of this function for such attributes do nothing.
307 */
nfexp_set_attr(struct nf_expect * exp,const enum nf_expect_attr type,const void * value)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
324 /**
325 * nfexp_set_attr_u8 - set the value of a certain expect attribute
326 * \param exp pointer to a valid expect
327 * \param type attribute type
328 * \param value unsigned 8 bits attribute value
329 */
nfexp_set_attr_u8(struct nf_expect * exp,const enum nf_expect_attr type,uint8_t value)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
337 /**
338 * nfexp_set_attr_u16 - set the value of a certain expect attribute
339 * \param exp pointer to a valid expect
340 * \param type attribute type
341 * \param value unsigned 16 bits attribute value
342 */
nfexp_set_attr_u16(struct nf_expect * exp,const enum nf_expect_attr type,uint16_t value)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
350 /**
351 * nfexp_set_attr_u32 - set the value of a certain expect attribute
352 * \param exp pointer to a valid expect
353 * \param type attribute type
354 * \param value unsigned 32 bits attribute value
355 */
nfexp_set_attr_u32(struct nf_expect * exp,const enum nf_expect_attr type,uint32_t value)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
363 /**
364 * nfexp_get_attr - get an expect attribute
365 * \param exp pointer to a valid expect
366 * \param type attribute type
367 *
368 * In case of success a valid pointer to the attribute requested is returned,
369 * on error NULL is returned and errno is set appropiately.
370 */
nfexp_get_attr(const struct nf_expect * exp,const enum nf_expect_attr type)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
389 /**
390 * nfexp_get_attr_u8 - get attribute of unsigned 8-bits long
391 * \param exp pointer to a valid expectation
392 * \param type attribute type
393 *
394 * Returns the value of the requested attribute, if the attribute is not
395 * set, 0 is returned. In order to check if the attribute is set or not,
396 * use nfexp_attr_is_set.
397 */
nfexp_get_attr_u8(const struct nf_expect * exp,const enum nf_expect_attr type)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
405 /**
406 * nfexp_get_attr_u16 - get attribute of unsigned 16-bits long
407 * \param exp pointer to a valid expectation
408 * \param type attribute type
409 *
410 * Returns the value of the requested attribute, if the attribute is not
411 * set, 0 is returned. In order to check if the attribute is set or not,
412 * use nfexp_attr_is_set.
413 */
nfexp_get_attr_u16(const struct nf_expect * exp,const enum nf_expect_attr type)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
421 /**
422 * nfexp_get_attr_u32 - get attribute of unsigned 32-bits long
423 * \param exp pointer to a valid expectation
424 * \param type attribute type
425 *
426 * Returns the value of the requested attribute, if the attribute is not
427 * set, 0 is returned. In order to check if the attribute is set or not,
428 * use nfexp_attr_is_set.
429 */
nfexp_get_attr_u32(const struct nf_expect * exp,const enum nf_expect_attr type)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
437 /**
438 * nfexp_attr_is_set - check if a certain attribute is set
439 * \param exp pointer to a valid expectation object
440 * \param type attribute type
441 *
442 * On error, -1 is returned and errno is set appropiately, otherwise
443 * the value of the attribute is returned.
444 */
nfexp_attr_is_set(const struct nf_expect * exp,const enum nf_expect_attr type)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
457 /**
458 * nfexp_attr_unset - unset a certain attribute
459 * \param type attribute type
460 * \param exp pointer to a valid expectation object
461 *
462 * On error, -1 is returned and errno is set appropiately, otherwise
463 * 0 is returned.
464 */
nfexp_attr_unset(struct nf_expect * exp,const enum nf_expect_attr type)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
479 /**
480 * @}
481 */
482
483 /**
484 * \defgroup nl Low level object to Netlink message
485 * @{
486 */
487
488 /**
489 * nfexp_build_expect - build a netlink message from a conntrack object
490 * \param ssh nfnetlink subsystem handler
491 * \param req buffer used to build the netlink message
492 * \param size size of the buffer passed
493 * \param type netlink message type
494 * \param flags netlink flags
495 * \param exp pointer to a conntrack object
496 *
497 * This is a low level function for those that require to be close to
498 * netlink details via libnfnetlink. If you do want to obviate the netlink
499 * details then we suggest you to use nfexp_query.
500 *
501 * On error, -1 is returned and errno is appropiately set.
502 * On success, 0 is returned.
503 */
nfexp_build_expect(struct nfnl_subsys_handle * ssh,void * req,size_t size,uint16_t type,uint16_t flags,const struct nf_expect * exp)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
__build_query_exp(struct nfnl_subsys_handle * ssh,const enum nf_conntrack_query qt,const void * data,void * buffer,unsigned int size)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
558 /**
559 * nfexp_build_query - build a query in netlink message format for ctnetlink
560 * \param ssh nfnetlink subsystem handler
561 * \param qt query type
562 * \param data data required to build the query
563 * \param req buffer to build the netlink message
564 * \param size size of the buffer passed
565 *
566 * This is a low level function, use it if you want to require to work
567 * with netlink details via libnfnetlink, otherwise we suggest you to
568 * use nfexp_query.
569 *
570 * The pointer to data can be a conntrack object or the protocol family
571 * depending on the request.
572 *
573 * For query types:
574 * NFEXP_Q_CREATE
575 * NFEXP_Q_DESTROY
576 *
577 * Pass a valid pointer to an expectation object.
578 *
579 * For query types:
580 * NFEXP_Q_FLUSH
581 * NFEXP_Q_DUMP
582 *
583 * Pass a valid pointer to the protocol family (uint8_t)
584 *
585 * On success, 0 is returned. On error, -1 is returned and errno is set
586 * appropiately.
587 */
nfexp_build_query(struct nfnl_subsys_handle * ssh,const enum nf_conntrack_query qt,const void * data,void * buffer,unsigned int size)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
597 /**
598 * nfexp_parse_expect - translate a netlink message to a conntrack object
599 * \param type do the translation iif the message type is of a certain type
600 * \param nlh pointer to the netlink message
601 * \param exp pointer to the conntrack object
602 *
603 * This is a low level function, use it in case that you require to work
604 * with netlink details via libnfnetlink. Otherwise, we suggest you to
605 * use the high level API.
606 *
607 * The message types are:
608 *
609 * NFEXP_T_NEW: parse messages with new conntracks
610 * NFEXP_T_UPDATE: parse messages with conntrack updates
611 * NFEXP_T_DESTROY: parse messages with conntrack destroy
612 * NFEXP_T_ALL: all message types
613 *
614 * The message type is a flag, therefore the can be combined, ie.
615 * NFEXP_T_NEW | NFEXP_T_DESTROY to parse only new and destroy messages
616 *
617 * On error, NFEXP_T_ERROR is returned and errno is set appropiately. If
618 * the message received is not of the requested type then 0 is returned,
619 * otherwise this function returns the message type parsed.
620 */
nfexp_parse_expect(enum nf_conntrack_msg_type type,const struct nlmsghdr * nlh,struct nf_expect * exp)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
650 /**
651 * @}
652 */
653
654 /**
655 * \defgroup cmd Send commands to kernel-space and receive replies
656 * @{
657 */
658
659 /**
660 * nfexp_query - send a query to ctnetlink
661 * \param h library handler
662 * \param qt query type
663 * \param data data required to send the query
664 *
665 * On error, -1 is returned and errno is explicitely set. On success, 0
666 * is returned.
667 */
nfexp_query(struct nfct_handle * h,const enum nf_conntrack_query qt,const void * data)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
687 /**
688 * nfexp_send - send a query to ctnetlink
689 * \param h library handler
690 * \param qt query type
691 * \param data data required to send the query
692 *
693 * Like nfexp_query but we do not wait for the reply from ctnetlink.
694 * You can use nfexp_send() and nfexp_catch() to emulate nfexp_query().
695 * This is particularly useful when the socket is non-blocking.
696 *
697 * On error, -1 is returned and errno is explicitely set. On success, 0
698 * is returned.
699 */
nfexp_send(struct nfct_handle * h,const enum nf_conntrack_query qt,const void * data)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
719 /**
720 * nfexp_catch - catch events
721 * \param h library handler
722 *
723 * This function receives the event from the kernel and it invokes the
724 * callback that was registered to this handle.
725 *
726 * On error, -1 is returned and errno is set appropiately. On success,
727 * a value greater or equal to 0 is returned indicating the callback
728 * verdict: NFCT_CB_STOP, NFCT_CB_CONTINUE or NFCT_CB_STOLEN.
729 *
730 * Beware that this function is equivalent to nfct_catch(), so it handles both
731 * conntrack and expectation events.
732 */
nfexp_catch(struct nfct_handle * h)733 int nfexp_catch(struct nfct_handle *h)
734 {
735 assert(h != NULL);
736
737 return nfnl_catch(h->nfnlh);
738 }
739
740 /**
741 * @}
742 */
743
744 /**
745 * \defgroup exp Expect object handling
746 * @{
747 */
748
749 /**
750 * nfexp_snprintf - print a conntrack object to a buffer
751 * \param buf buffer used to build the printable conntrack
752 * \param size size of the buffer
753 * \param exp pointer to a valid expectation object
754 * \param message_type print message type (NFEXP_T_UNKNOWN, NFEXP_T_NEW,...)
755 * \param output_type print type (NFEXP_O_DEFAULT, NFEXP_O_XML, ...)
756 * \param flags extra flags for the output type (NFEXP_OF_LAYER3)
757 *
758 * If you are listening to events, probably you want to display the message
759 * type as well. In that case, set the message type parameter to any of the
760 * known existing types, ie. NFEXP_T_NEW, NFEXP_T_UPDATE, NFEXP_T_DESTROY.
761 * If you pass NFEXP_T_UNKNOWN, the message type will not be output.
762 *
763 * Currently, the output available are:
764 * - NFEXP_O_DEFAULT: default /proc-like output
765 * - NFEXP_O_XML: XML output
766 *
767 * The output flags are:
768 * - NFEXP_O_LAYER: include layer 3 information in the output, this is
769 * *only* required by NFEXP_O_DEFAULT.
770 *
771 * On error, -1 is returned and errno is set appropiately. Otherwise,
772 * 0 is returned.
773 */
nfexp_snprintf(char * buf,unsigned int size,const struct nf_expect * exp,unsigned int msg_type,unsigned int out_type,unsigned int flags)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
788 /**
789 * @}
790 */
791