Home | History | Annotate | Download | only in expect
      1 /*
      2  * (C) 2005-2011 by Pablo Neira Ayuso <pablo (at) 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  */
     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  */
     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  */
     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  */
     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  */
     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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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