• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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