• 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 <stdbool.h>
12 #include <string.h> /* for memset */
13 #include <errno.h>
14 #include <assert.h>
15 
16 #include "internal/internal.h"
17 
18 /**
19  * \mainpage
20  *
21  * libnetfilter_conntrack is a userspace library providing a programming
22  * interface (API) to the in-kernel connection tracking state table. The
23  * library libnetfilter_conntrack has been previously known as
24  * libnfnetlink_conntrack and libctnetlink. This library is currently used by
25  * conntrack-tools among many other applications.
26  *
27  * libnetfilter_conntrack homepage is:
28  *      http://netfilter.org/projects/libnetfilter_conntrack/
29  *
30  * \section Dependencies
31  * libnetfilter_conntrack requires libnfnetlink and a kernel that includes the
32  * nf_conntrack_netlink subsystem (i.e. 2.6.14 or later, >= 2.6.18 recommended).
33  *
34  * \section Main Features
35  *  - listing/retrieving entries from the kernel connection tracking table.
36  *  - inserting/modifying/deleting entries from the kernel connection tracking
37  *    table.
38  *  - listing/retrieving entries from the kernel expect table.
39  *  - inserting/modifying/deleting entries from the kernel expect table.
40  * \section Git Tree
41  * The current development version of libnetfilter_conntrack can be accessed at
42  * https://git.netfilter.org/cgi-bin/gitweb.cgi?p=libnetfilter_conntrack.git
43  *
44  * \section Privileges
45  * You need the CAP_NET_ADMIN capability in order to allow your application
46  * to receive events from and to send commands to kernel-space, excepting
47  * the conntrack table dumping operation.
48  *
49  * \section using Using libnetfilter_conntrack
50  * To write your own program using libnetfilter_conntrack, you should start by
51  * reading the doxygen documentation (start by \link LibrarySetup \endlink page)
52  * and check examples available under utils/ in the libnetfilter_conntrack
53  * source code tree. You can compile these examples by invoking `make check'.
54  *
55  * \section Authors
56  * libnetfilter_conntrack has been almost entirely written by Pablo Neira Ayuso.
57  *
58  * \section python Python Binding
59  * pynetfilter_conntrack is a Python binding of libnetfilter_conntrack written
60  * by Victor Stinner. You can visit his official web site at
61  * http://software.inl.fr/trac/trac.cgi/wiki/pynetfilter_conntrack.
62  */
63 
64 /**
65  * \defgroup ct Conntrack object handling
66  * @{
67  */
68 
69 /**
70  * nfct_conntrack_new - allocate a new conntrack
71  *
72  * In case of success, this function returns a valid pointer to a memory blob,
73  * otherwise NULL is returned and errno is set appropiately.
74  */
nfct_new(void)75 struct nf_conntrack *nfct_new(void)
76 {
77 	struct nf_conntrack *ct;
78 
79 	ct = malloc(sizeof(struct nf_conntrack));
80 	if (!ct)
81 		return NULL;
82 
83 	memset(ct, 0, sizeof(struct nf_conntrack));
84 
85 	return ct;
86 }
87 
88 /**
89  * nf_conntrack_destroy - release a conntrack object
90  * \param ct pointer to the conntrack object
91  */
nfct_destroy(struct nf_conntrack * ct)92 void nfct_destroy(struct nf_conntrack *ct)
93 {
94 	assert(ct != NULL);
95 	if (ct->secctx)
96 		free(ct->secctx);
97 	if (ct->helper_info)
98 		free(ct->helper_info);
99 	if (ct->connlabels)
100 		nfct_bitmask_destroy(ct->connlabels);
101 	if (ct->connlabels_mask)
102 		nfct_bitmask_destroy(ct->connlabels_mask);
103 	free(ct);
104 	ct = NULL; /* bugtrap */
105 }
106 
107 /**
108  * nf_sizeof - return the size in bytes of a certain conntrack object
109  * \param ct pointer to the conntrack object
110  *
111  * This function is DEPRECATED, don't use it in your code.
112  */
nfct_sizeof(const struct nf_conntrack * ct)113 size_t nfct_sizeof(const struct nf_conntrack *ct)
114 {
115 	assert(ct != NULL);
116 	return sizeof(*ct);
117 }
118 
119 /**
120  * nfct_maxsize - return the maximum size in bytes of a conntrack object
121  *
122  * Use this function if you want to allocate a conntrack object in the stack
123  * instead of the heap. For example:
124  * \verbatim
125 	char buf[nfct_maxsize()];
126 	struct nf_conntrack *ct = (struct nf_conntrack *) buf;
127 	memset(ct, 0, nfct_maxsize());
128 \endverbatim
129  * Note: As for now this function returns the same size that nfct_sizeof(ct)
130  * does although _this could change in the future_. Therefore, do not assume
131  * that nfct_sizeof(ct) == nfct_maxsize().
132  *
133  * This function is DEPRECATED, don't use it in your code.
134  */
nfct_maxsize(void)135 size_t nfct_maxsize(void)
136 {
137 	return sizeof(struct nf_conntrack);
138 }
139 
140 /**
141  * nfct_clone - clone a conntrack object
142  * \param ct pointer to a valid conntrack object
143  *
144  * On error, NULL is returned and errno is appropiately set. Otherwise,
145  * a valid pointer to the clone conntrack is returned.
146  */
nfct_clone(const struct nf_conntrack * ct)147 struct nf_conntrack *nfct_clone(const struct nf_conntrack *ct)
148 {
149 	struct nf_conntrack *clone;
150 
151 	assert(ct != NULL);
152 
153 	if ((clone = nfct_new()) == NULL)
154 		return NULL;
155 	nfct_copy(clone, ct, NFCT_CP_OVERRIDE);
156 
157 	return clone;
158 }
159 
160 /**
161  * nfct_setobjopt - set a certain option for a conntrack object
162  * \param ct conntrack object
163  * \param option option parameter
164  *
165  * In case of error, -1 is returned and errno is appropiately set. On success,
166  * 0 is returned.
167  */
nfct_setobjopt(struct nf_conntrack * ct,unsigned int option)168 int nfct_setobjopt(struct nf_conntrack *ct, unsigned int option)
169 {
170 	assert(ct != NULL);
171 
172 	if (unlikely(option > NFCT_SOPT_MAX)) {
173 		errno = EOPNOTSUPP;
174 		return -1;
175 	}
176 
177 	return __setobjopt(ct, option);
178 }
179 
180 /**
181  * nfct_getobjopt - get a certain option for a conntrack object
182  * \param ct conntrack object
183  * \param option option parameter
184  *
185  * In case of error, -1 is returned and errno is appropiately set. On success,
186  * 0 is returned.
187  */
nfct_getobjopt(const struct nf_conntrack * ct,unsigned int option)188 int nfct_getobjopt(const struct nf_conntrack *ct, unsigned int option)
189 {
190 	assert(ct != NULL);
191 
192 	if (unlikely(option > NFCT_GOPT_MAX)) {
193 		errno = EOPNOTSUPP;
194 		return -1;
195 	}
196 
197 	return __getobjopt(ct, option);
198 }
199 
200 /**
201  * @}
202  */
203 
204 /**
205  * \defgroup LibrarySetup Library setup
206  * @{
207  */
208 
209 /**
210  * nf_callback_register - register a callback
211  * \param h library handler
212  * \param type message type (see enum nf_conntrack_msg_type definition)
213  * \param cb callback used to process conntrack received
214  * \param data data used by the callback, if any.
215  *
216  * This function register a callback to handle the conntrack received,
217  * in case of error -1 is returned and errno is set appropiately, otherwise
218  * 0 is returned.
219  *
220  * Note that the data parameter is optional, if you do not want to pass any
221  * data to your callback, then use NULL.
222  */
nfct_callback_register(struct nfct_handle * h,enum nf_conntrack_msg_type type,int (* cb)(enum nf_conntrack_msg_type type,struct nf_conntrack * ct,void * data),void * data)223 int nfct_callback_register(struct nfct_handle *h,
224 			   enum nf_conntrack_msg_type type,
225 			   int (*cb)(enum nf_conntrack_msg_type type,
226 			   	     struct nf_conntrack *ct,
227 				     void *data),
228 			   void *data)
229 {
230 	struct __data_container *container;
231 
232 	assert(h != NULL);
233 
234 	container = malloc(sizeof(struct __data_container));
235 	if (!container)
236 		return -1;
237 	memset(container, 0, sizeof(struct __data_container));
238 
239 	h->cb = cb;
240 	container->h = h;
241 	container->type = type;
242 	container->data = data;
243 
244 	h->nfnl_cb_ct.call = __callback;
245 	h->nfnl_cb_ct.data = container;
246 	h->nfnl_cb_ct.attr_count = CTA_MAX;
247 
248 	nfnl_callback_register(h->nfnlssh_ct,
249 			       IPCTNL_MSG_CT_NEW,
250 			       &h->nfnl_cb_ct);
251 
252 	nfnl_callback_register(h->nfnlssh_ct,
253 			       IPCTNL_MSG_CT_DELETE,
254 			       &h->nfnl_cb_ct);
255 
256 	return 0;
257 }
258 
259 /**
260  * nfct_callback_unregister - unregister a callback
261  * \param h library handler
262  */
nfct_callback_unregister(struct nfct_handle * h)263 void nfct_callback_unregister(struct nfct_handle *h)
264 {
265 	assert(h != NULL);
266 
267 	nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
268 	nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
269 
270 	h->cb = NULL;
271 	free(h->nfnl_cb_ct.data);
272 
273 	h->nfnl_cb_ct.call = NULL;
274 	h->nfnl_cb_ct.data = NULL;
275 	h->nfnl_cb_ct.attr_count = 0;
276 }
277 
278 /**
279  * nf_callback_register2 - register a callback
280  * \param h library handler
281  * \param cb callback used to process conntrack received
282  * \param data data used by the callback, if any.
283  *
284  * This function register a callback to handle the conntrack received,
285  * in case of error -1 is returned and errno is set appropiately, otherwise
286  * 0 is returned.
287  *
288  * Note that the data parameter is optional, if you do not want to pass any
289  * data to your callback, then use NULL.
290  *
291  * NOTICE: The difference with nf_callback_register() is that this function
292  * uses the new callback interface that includes the Netlink header.
293  *
294  * WARNING: Don't mix nf_callback_register() and nf_callback_register2()
295  * calls, use only once at a time.
296  */
nfct_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_conntrack * ct,void * data),void * data)297 int nfct_callback_register2(struct nfct_handle *h,
298 			    enum nf_conntrack_msg_type type,
299 			    int (*cb)(const struct nlmsghdr *nlh,
300 			    	      enum nf_conntrack_msg_type type,
301 				      struct nf_conntrack *ct,
302 				      void *data),
303 			   void *data)
304 {
305 	struct __data_container *container;
306 
307 	assert(h != NULL);
308 
309 	container = calloc(sizeof(struct __data_container), 1);
310 	if (container == NULL)
311 		return -1;
312 
313 	h->cb2 = cb;
314 	container->h = h;
315 	container->type = type;
316 	container->data = data;
317 
318 	h->nfnl_cb_ct.call = __callback;
319 	h->nfnl_cb_ct.data = container;
320 	h->nfnl_cb_ct.attr_count = CTA_MAX;
321 
322 	nfnl_callback_register(h->nfnlssh_ct,
323 			       IPCTNL_MSG_CT_NEW,
324 			       &h->nfnl_cb_ct);
325 
326 	nfnl_callback_register(h->nfnlssh_ct,
327 			       IPCTNL_MSG_CT_DELETE,
328 			       &h->nfnl_cb_ct);
329 
330 	return 0;
331 }
332 
333 /**
334  * nfct_callback_unregister2 - unregister a callback
335  * \param h library handler
336  */
nfct_callback_unregister2(struct nfct_handle * h)337 void nfct_callback_unregister2(struct nfct_handle *h)
338 {
339 	assert(h != NULL);
340 
341 	nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_NEW);
342 	nfnl_callback_unregister(h->nfnlssh_ct, IPCTNL_MSG_CT_DELETE);
343 
344 	h->cb2 = NULL;
345 	free(h->nfnl_cb_ct.data);
346 
347 	h->nfnl_cb_ct.call = NULL;
348 	h->nfnl_cb_ct.data = NULL;
349 	h->nfnl_cb_ct.attr_count = 0;
350 }
351 
352 /**
353  * @}
354  */
355 
356 /**
357  * \defgroup ct Conntrack object handling
358  * @{
359  */
360 
361 /**
362  * nfct_set_attr_l - set the value of a certain conntrack attribute
363  * \param ct pointer to a valid conntrack
364  * \param type attribute type
365  * \param pointer to attribute value
366  * \param length of attribute value (in bytes)
367  */
368 void
nfct_set_attr_l(struct nf_conntrack * ct,const enum nf_conntrack_attr type,const void * value,size_t len)369 nfct_set_attr_l(struct nf_conntrack *ct, const enum nf_conntrack_attr type,
370 		const void *value, size_t len)
371 {
372 	assert(ct != NULL);
373 	assert(value != NULL);
374 
375 	if (unlikely(type >= ATTR_MAX))
376 		return;
377 
378 	if (set_attr_array[type]) {
379 		set_attr_array[type](ct, value, len);
380 		set_bit(type, ct->head.set);
381 	}
382 }
383 
384 /**
385  * nfct_set_attr - set the value of a certain conntrack attribute
386  * \param ct pointer to a valid conntrack
387  * \param type attribute type
388  * \param value pointer to the attribute value
389  *
390  * Note that certain attributes are unsettable:
391  * 	- ATTR_USE
392  * 	- ATTR_ID
393  * 	- ATTR_*_COUNTER_*
394  *	- ATTR_SECCTX
395  *	- ATTR_TIMESTAMP_*
396  * The call of this function for such attributes do nothing.
397  */
nfct_set_attr(struct nf_conntrack * ct,const enum nf_conntrack_attr type,const void * value)398 void nfct_set_attr(struct nf_conntrack *ct,
399 		   const enum nf_conntrack_attr type,
400 		   const void *value)
401 {
402 	/* We assume the setter knows the size of the passed pointer. */
403 	nfct_set_attr_l(ct, type, value, 0);
404 }
405 
406 /**
407  * nfct_set_attr_u8 - set the value of a certain conntrack attribute
408  * \param ct pointer to a valid conntrack
409  * \param type attribute type
410  * \param value unsigned 8 bits attribute value
411  */
nfct_set_attr_u8(struct nf_conntrack * ct,const enum nf_conntrack_attr type,uint8_t value)412 void nfct_set_attr_u8(struct nf_conntrack *ct,
413 		      const enum nf_conntrack_attr type,
414 		      uint8_t value)
415 {
416 	nfct_set_attr_l(ct, type, &value, sizeof(uint8_t));
417 }
418 
419 /**
420  * nfct_set_attr_u16 - set the value of a certain conntrack attribute
421  * \param ct pointer to a valid conntrack
422  * \param type attribute type
423  * \param value unsigned 16 bits attribute value
424  */
nfct_set_attr_u16(struct nf_conntrack * ct,const enum nf_conntrack_attr type,uint16_t value)425 void nfct_set_attr_u16(struct nf_conntrack *ct,
426 		       const enum nf_conntrack_attr type,
427 		       uint16_t value)
428 {
429 	nfct_set_attr_l(ct, type, &value, sizeof(uint16_t));
430 }
431 
432 /**
433  * nfct_set_attr_u32 - set the value of a certain conntrack attribute
434  * \param ct pointer to a valid conntrack
435  * \param type attribute type
436  * \param value unsigned 32 bits attribute value
437  */
nfct_set_attr_u32(struct nf_conntrack * ct,const enum nf_conntrack_attr type,uint32_t value)438 void nfct_set_attr_u32(struct nf_conntrack *ct,
439 		       const enum nf_conntrack_attr type,
440 		       uint32_t value)
441 {
442 	nfct_set_attr_l(ct, type, &value, sizeof(uint32_t));
443 }
444 
445 /**
446  * nfct_set_attr_u64 - set the value of a certain conntrack attribute
447  * \param ct pointer to a valid conntrack
448  * \param type attribute type
449  * \param value unsigned 64 bits attribute value
450  */
nfct_set_attr_u64(struct nf_conntrack * ct,const enum nf_conntrack_attr type,uint64_t value)451 void nfct_set_attr_u64(struct nf_conntrack *ct,
452 		       const enum nf_conntrack_attr type,
453 		       uint64_t value)
454 {
455 	nfct_set_attr_l(ct, type, &value, sizeof(uint64_t));
456 }
457 
458 /**
459  * nfct_get_attr - get a conntrack attribute
460  * \param ct pointer to a valid conntrack
461  * \param type attribute type
462  *
463  * In case of success a valid pointer to the attribute requested is returned,
464  * on error NULL is returned and errno is set appropiately.
465  */
nfct_get_attr(const struct nf_conntrack * ct,const enum nf_conntrack_attr type)466 const void *nfct_get_attr(const struct nf_conntrack *ct,
467 			  const enum nf_conntrack_attr type)
468 {
469 	assert(ct != NULL);
470 
471 	if (unlikely(type >= ATTR_MAX)) {
472 		errno = EINVAL;
473 		return NULL;
474 	}
475 
476 	if (!test_bit(type, ct->head.set)) {
477 		errno = ENODATA;
478 		return NULL;
479 	}
480 
481 	assert(get_attr_array[type]);
482 
483 	return get_attr_array[type](ct);
484 }
485 
486 /**
487  * nfct_get_attr_u8 - get attribute of unsigned 8-bits long
488  * \param ct pointer to a valid conntrack
489  * \param type attribute type
490  *
491  * Returns the value of the requested attribute, if the attribute is not
492  * set, 0 is returned. In order to check if the attribute is set or not,
493  * use nfct_attr_is_set.
494  */
nfct_get_attr_u8(const struct nf_conntrack * ct,const enum nf_conntrack_attr type)495 uint8_t nfct_get_attr_u8(const struct nf_conntrack *ct,
496 			  const enum nf_conntrack_attr type)
497 {
498 	const uint8_t *ret = nfct_get_attr(ct, type);
499 	return ret == NULL ? 0 : *ret;
500 }
501 
502 /**
503  * nfct_get_attr_u16 - get attribute of unsigned 16-bits long
504  * \param ct pointer to a valid conntrack
505  * \param type attribute type
506  *
507  * Returns the value of the requested attribute, if the attribute is not
508  * set, 0 is returned. In order to check if the attribute is set or not,
509  * use nfct_attr_is_set.
510  */
nfct_get_attr_u16(const struct nf_conntrack * ct,const enum nf_conntrack_attr type)511 uint16_t nfct_get_attr_u16(const struct nf_conntrack *ct,
512 			    const enum nf_conntrack_attr type)
513 {
514 	const uint16_t *ret = nfct_get_attr(ct, type);
515 	return ret == NULL ? 0 : *ret;
516 }
517 
518 /**
519  * nfct_get_attr_u32 - get attribute of unsigned 32-bits long
520  * \param ct pointer to a valid conntrack
521  * \param type attribute type
522  *
523  * Returns the value of the requested attribute, if the attribute is not
524  * set, 0 is returned. In order to check if the attribute is set or not,
525  * use nfct_attr_is_set.
526  */
nfct_get_attr_u32(const struct nf_conntrack * ct,const enum nf_conntrack_attr type)527 uint32_t nfct_get_attr_u32(const struct nf_conntrack *ct,
528 			    const enum nf_conntrack_attr type)
529 {
530 	const uint32_t *ret = nfct_get_attr(ct, type);
531 	return ret == NULL ? 0 : *ret;
532 }
533 
534 /**
535  * nfct_get_attr_u64 - get attribute of unsigned 32-bits long
536  * \param ct pointer to a valid conntrack
537  * \param type attribute type
538  *
539  * Returns the value of the requested attribute, if the attribute is not
540  * set, 0 is returned. In order to check if the attribute is set or not,
541  * use nfct_attr_is_set.
542  */
nfct_get_attr_u64(const struct nf_conntrack * ct,const enum nf_conntrack_attr type)543 uint64_t nfct_get_attr_u64(const struct nf_conntrack *ct,
544 			    const enum nf_conntrack_attr type)
545 {
546 	const uint64_t *ret = nfct_get_attr(ct, type);
547 	return ret == NULL ? 0 : *ret;
548 }
549 
550 /**
551  * nfct_attr_is_set - check if a certain attribute is set
552  * \param ct pointer to a valid conntrack object
553  * \param type attribute type
554  *
555  * On error, -1 is returned and errno is set appropiately, otherwise
556  * the value of the attribute is returned.
557  */
nfct_attr_is_set(const struct nf_conntrack * ct,const enum nf_conntrack_attr type)558 int nfct_attr_is_set(const struct nf_conntrack *ct,
559 		     const enum nf_conntrack_attr type)
560 {
561 	assert(ct != NULL);
562 
563 	if (unlikely(type >= ATTR_MAX)) {
564 		errno = EINVAL;
565 		return -1;
566 	}
567 	return test_bit(type, ct->head.set);
568 }
569 
570 /**
571  * nfct_attr_is_set_array - check if an array of attribute types is set
572  * \param ct pointer to a valid conntrack object
573  * \param array attribute type array
574  * \param size size of the array
575  *
576  * On error, -1 is returned and errno is set appropiately, otherwise
577  * the value of the attribute is returned.
578  */
nfct_attr_is_set_array(const struct nf_conntrack * ct,const enum nf_conntrack_attr * type_array,int size)579 int nfct_attr_is_set_array(const struct nf_conntrack *ct,
580 			   const enum nf_conntrack_attr *type_array,
581 			   int size)
582 {
583 	int i;
584 
585 	assert(ct != NULL);
586 
587 	for (i=0; i<size; i++) {
588 		if (unlikely(type_array[i] >= ATTR_MAX)) {
589 			errno = EINVAL;
590 			return -1;
591 		}
592 		if (!test_bit(type_array[i], ct->head.set))
593 			return 0;
594 	}
595 	return 1;
596 }
597 
598 /**
599  * nfct_attr_unset - unset a certain attribute
600  * \param type attribute type
601  * \param ct pointer to a valid conntrack object
602  *
603  * On error, -1 is returned and errno is set appropiately, otherwise
604  * 0 is returned.
605  */
nfct_attr_unset(struct nf_conntrack * ct,const enum nf_conntrack_attr type)606 int nfct_attr_unset(struct nf_conntrack *ct,
607 		    const enum nf_conntrack_attr type)
608 {
609 	assert(ct != NULL);
610 
611 	if (unlikely(type >= ATTR_MAX)) {
612 		errno = EINVAL;
613 		return -1;
614 	}
615 	unset_bit(type, ct->head.set);
616 
617 	return 0;
618 }
619 
620 /**
621  * nfct_set_attr_grp - set a group of attributes
622  * \param ct pointer to a valid conntrack object
623  * \param type attribute group (see ATTR_GRP_*)
624  * \param data pointer to struct (see struct nfct_attr_grp_*)
625  *
626  * Note that calling this function for ATTR_GRP_COUNTER_* and ATTR_GRP_ADDR_*
627  * have no effect.
628  */
nfct_set_attr_grp(struct nf_conntrack * ct,const enum nf_conntrack_attr_grp type,const void * data)629 void nfct_set_attr_grp(struct nf_conntrack *ct,
630 		       const enum nf_conntrack_attr_grp type,
631 		       const void *data)
632 {
633 	assert(ct != NULL);
634 
635 	if (unlikely(type >= ATTR_GRP_MAX))
636 		return;
637 
638 	if (set_attr_grp_array[type]) {
639 		set_attr_grp_array[type](ct, data);
640 		set_bitmask_u32(ct->head.set,
641 				attr_grp_bitmask[type].bitmask, __NFCT_BITSET);
642 	}
643 }
644 
645 /**
646  * nfct_get_attr_grp - get an attribute group
647  * \param ct pointer to a valid conntrack object
648  * \param type attribute group (see ATTR_GRP_*)
649  * \param data pointer to struct (see struct nfct_attr_grp_*)
650  *
651  * On error, it returns -1 and errno is appropriately set. On success, the
652  * data pointer contains the attribute group.
653  */
nfct_get_attr_grp(const struct nf_conntrack * ct,const enum nf_conntrack_attr_grp type,void * data)654 int nfct_get_attr_grp(const struct nf_conntrack *ct,
655 		      const enum nf_conntrack_attr_grp type,
656 		      void *data)
657 {
658 	assert(ct != NULL);
659 
660 	if (unlikely(type >= ATTR_GRP_MAX)) {
661 		errno = EINVAL;
662 		return -1;
663 	}
664 	switch(attr_grp_bitmask[type].type) {
665 	case NFCT_BITMASK_AND:
666 		if (!test_bitmask_u32(ct->head.set,
667 				      attr_grp_bitmask[type].bitmask,
668 				      __NFCT_BITSET)) {
669 			errno = ENODATA;
670 			return -1;
671 		}
672 		break;
673 	case NFCT_BITMASK_OR:
674 		if (!test_bitmask_u32_or(ct->head.set,
675 					 attr_grp_bitmask[type].bitmask,
676 					 __NFCT_BITSET)) {
677 			errno = ENODATA;
678 			return -1;
679 		}
680 		break;
681 	}
682 	assert(get_attr_grp_array[type]);
683 	get_attr_grp_array[type](ct, data);
684 	return 0;
685 }
686 
687 /**
688  * nfct_attr_grp_is_set - check if an attribute group is set
689  * \param ct pointer to a valid conntrack object
690  * \param type attribute group (see ATTR_GRP_*)
691  *
692  * If the attribute group is set, this function returns 1, otherwise 0.
693  */
nfct_attr_grp_is_set(const struct nf_conntrack * ct,const enum nf_conntrack_attr_grp type)694 int nfct_attr_grp_is_set(const struct nf_conntrack *ct,
695 			 const enum nf_conntrack_attr_grp type)
696 {
697 	assert(ct != NULL);
698 
699 	if (unlikely(type >= ATTR_GRP_MAX)) {
700 		errno = EINVAL;
701 		return -1;
702 	}
703 	switch(attr_grp_bitmask[type].type) {
704 	case NFCT_BITMASK_AND:
705 		if (test_bitmask_u32(ct->head.set,
706 				     attr_grp_bitmask[type].bitmask,
707 				     __NFCT_BITSET)) {
708 			return 1;
709 		}
710 		break;
711 	case NFCT_BITMASK_OR:
712 		if (test_bitmask_u32_or(ct->head.set,
713 					attr_grp_bitmask[type].bitmask,
714 					__NFCT_BITSET)) {
715 			return 1;
716 		}
717 		break;
718 	}
719 	return 0;
720 }
721 
722 /**
723  * nfct_attr_grp_unset - unset an attribute group
724  * \param ct pointer to a valid conntrack object
725  * \param type attribute group (see ATTR_GRP_*)
726  *
727  * On error, it returns -1 and errno is appropriately set. On success,
728  * this function returns 0.
729  */
nfct_attr_grp_unset(struct nf_conntrack * ct,const enum nf_conntrack_attr_grp type)730 int nfct_attr_grp_unset(struct nf_conntrack *ct,
731 			const enum nf_conntrack_attr_grp type)
732 {
733 	assert(ct != NULL);
734 
735 	if (unlikely(type >= ATTR_GRP_MAX)) {
736 		errno = EINVAL;
737 		return -1;
738 	}
739 	unset_bitmask_u32(ct->head.set, attr_grp_bitmask[type].bitmask,
740 			  __NFCT_BITSET);
741 
742 	return 0;
743 }
744 
745 /**
746  * @}
747  */
748 
749 /**
750  * \defgroup nl Low level object to Netlink message
751  * @{
752  */
753 
754 /**
755  * nfct_build_conntrack - build a netlink message from a conntrack object
756  * \param ssh nfnetlink subsystem handler
757  * \param req buffer used to build the netlink message
758  * \param size size of the buffer passed
759  * \param type netlink message type
760  * \param flags netlink flags
761  * \param ct pointer to a conntrack object
762  *
763  * This is a low level function for those that require to be close to
764  * netlink details via libnfnetlink. If you do want to obviate the netlink
765  * details then we suggest you to use nfct_query.
766  *
767  * On error, -1 is returned and errno is appropiately set.
768  * On success, 0 is returned.
769  */
nfct_build_conntrack(struct nfnl_subsys_handle * ssh,void * req,size_t size,uint16_t type,uint16_t flags,const struct nf_conntrack * ct)770 int nfct_build_conntrack(struct nfnl_subsys_handle *ssh,
771 			 void *req,
772 			 size_t size,
773 			 uint16_t type,
774 			 uint16_t flags,
775 			 const struct nf_conntrack *ct)
776 {
777 	assert(ssh != NULL);
778 	assert(req != NULL);
779 	assert(ct != NULL);
780 
781 	return __build_conntrack(ssh, req, size, type, flags, ct);
782 }
783 
784 static int
__build_query_ct(struct nfnl_subsys_handle * ssh,const enum nf_conntrack_query qt,const void * data,void * buffer,unsigned int size)785 __build_query_ct(struct nfnl_subsys_handle *ssh,
786 		 const enum nf_conntrack_query qt,
787 		 const void *data, void *buffer, unsigned int size)
788 {
789 	struct nfnlhdr *req = buffer;
790 	const uint32_t *family = data;
791 
792 	assert(ssh != NULL);
793 	assert(data != NULL);
794 	assert(req != NULL);
795 
796 	memset(req, 0, size);
797 
798 	switch(qt) {
799 	case NFCT_Q_CREATE:
800 		__build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
801 		break;
802 	case NFCT_Q_UPDATE:
803 		__build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_ACK, data);
804 		break;
805 	case NFCT_Q_DESTROY:
806 		__build_conntrack(ssh, req, size, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
807 		break;
808 	case NFCT_Q_GET:
809 		__build_conntrack(ssh, req, size, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_ACK, data);
810 		break;
811 	case NFCT_Q_FLUSH:
812 		nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST|NLM_F_ACK);
813 		break;
814 	case NFCT_Q_DUMP:
815 		nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_DUMP);
816 		break;
817 	case NFCT_Q_DUMP_RESET:
818 		nfnl_fill_hdr(ssh, &req->nlh, 0, *family, 0, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_REQUEST|NLM_F_DUMP);
819 		break;
820 	case NFCT_Q_CREATE_UPDATE:
821 		__build_conntrack(ssh, req, size, IPCTNL_MSG_CT_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data);
822 		break;
823 	case NFCT_Q_DUMP_FILTER:
824 		nfnl_fill_hdr(ssh, &req->nlh, 0, AF_UNSPEC, 0, IPCTNL_MSG_CT_GET, NLM_F_REQUEST|NLM_F_DUMP);
825 		__build_filter_dump(req, size, data);
826 		break;
827 	case NFCT_Q_DUMP_FILTER_RESET:
828 		nfnl_fill_hdr(ssh, &req->nlh, 0, AF_UNSPEC, 0, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_REQUEST|NLM_F_DUMP);
829 		__build_filter_dump(req, size, data);
830 		break;
831 	default:
832 		errno = ENOTSUP;
833 		return -1;
834 	}
835 	return 1;
836 }
837 
838 /**
839  * nfct_build_query - build a query in netlink message format for ctnetlink
840  * \param ssh nfnetlink subsystem handler
841  * \param qt query type
842  * \param data data required to build the query
843  * \param req buffer to build the netlink message
844  * \param size size of the buffer passed
845  *
846  * This is a low level function, use it if you want to require to work
847  * with netlink details via libnfnetlink, otherwise we suggest you to
848  * use nfct_query.
849  *
850  * The pointer to data can be a conntrack object or the protocol family
851  * depending on the request.
852  *
853  * For query types:
854  * 	- NFCT_Q_CREATE: add a new conntrack, if it exists, fail
855  * 	- NFCT_O_CREATE_UPDATE: add a new conntrack, if it exists, update it
856  * 	- NFCT_Q_UPDATE: update a conntrack
857  * 	- NFCT_Q_DESTROY: destroy a conntrack
858  * 	- NFCT_Q_GET: get a conntrack
859  *
860  * Pass a valid pointer to a conntrack object.
861  *
862  * For query types:
863  * 	- NFCT_Q_FLUSH: flush the conntrack table
864  * 	- NFCT_Q_DUMP: dump the conntrack table
865  * 	- NFCT_Q_DUMP_RESET: dump the conntrack table and reset counters
866  * 	- NFCT_Q_DUMP_FILTER: dump the conntrack table
867  * 	- NFCT_Q_DUMP_FILTER_RESET: dump the conntrack table and reset counters
868  *
869  * Pass a valid pointer to the protocol family (uint32_t)
870  *
871  * On success, 0 is returned. On error, -1 is returned and errno is set
872  * appropiately.
873  */
nfct_build_query(struct nfnl_subsys_handle * ssh,const enum nf_conntrack_query qt,const void * data,void * buffer,unsigned int size)874 int nfct_build_query(struct nfnl_subsys_handle *ssh,
875 		     const enum nf_conntrack_query qt,
876 		     const void *data,
877 		     void *buffer,
878 		     unsigned int size)
879 {
880 	return __build_query_ct(ssh, qt, data, buffer, size);
881 }
882 
883 /**
884  * nfct_parse_conntrack - translate a netlink message to a conntrack object
885  * \param type do the translation iif the message type is of a certain type
886  * \param nlh pointer to the netlink message
887  * \param ct pointer to the conntrack object
888  *
889  * This is a low level function, use it in case that you require to work
890  * with netlink details via libnfnetlink. Otherwise, we suggest you to
891  * use the high level API.
892  *
893  * The message types are:
894  *
895  * - NFCT_T_NEW: parse messages with new conntracks
896  * - NFCT_T_UPDATE: parse messages with conntrack updates
897  * - NFCT_T_DESTROY: parse messages with conntrack destroy
898  * - NFCT_T_ALL: all message types
899  *
900  * The message type is a flag, therefore the can be combined, ie.
901  * NFCT_T_NEW | NFCT_T_DESTROY to parse only new and destroy messages
902  *
903  * On error, NFCT_T_ERROR is returned and errno is set appropiately. If
904  * the message received is not of the requested type then 0 is returned,
905  * otherwise this function returns the message type parsed.
906  */
nfct_parse_conntrack(enum nf_conntrack_msg_type type,const struct nlmsghdr * nlh,struct nf_conntrack * ct)907 int nfct_parse_conntrack(enum nf_conntrack_msg_type type,
908 			 const struct nlmsghdr *nlh,
909 			 struct nf_conntrack *ct)
910 {
911 	unsigned int flags;
912 	int len = nlh->nlmsg_len;
913 	struct nfgenmsg *nfhdr = NLMSG_DATA(nlh);
914 	struct nfattr *cda[CTA_MAX];
915 
916 	assert(nlh != NULL);
917 	assert(ct != NULL);
918 
919 	len -= NLMSG_LENGTH(sizeof(struct nfgenmsg));
920 	if (len < 0) {
921 		errno = EINVAL;
922 		return NFCT_T_ERROR;
923 	}
924 
925 	flags = __parse_message_type(nlh);
926 	if (!(flags & type))
927 		return 0;
928 
929 	nfnl_parse_attr(cda, CTA_MAX, NFA_DATA(nfhdr), len);
930 
931 	__parse_conntrack(nlh, cda, ct);
932 
933 	return flags;
934 }
935 
936 /**
937  * @}
938  */
939 
940 /**
941  * \defgroup cmd Send commands to kernel-space and receive replies
942  * @{
943  */
944 
945 /**
946  * nfct_query - send a query to ctnetlink and handle the reply
947  * \param h library handler
948  * \param qt query type
949  * \param data data required to send the query
950  *
951  * On error, -1 is returned and errno is explicitely set. On success, 0
952  * is returned.
953  */
nfct_query(struct nfct_handle * h,const enum nf_conntrack_query qt,const void * data)954 int nfct_query(struct nfct_handle *h,
955 	       const enum nf_conntrack_query qt,
956 	       const void *data)
957 {
958 	const size_t size = 4096;	/* enough for now */
959 	union {
960 		char buffer[size];
961 		struct nfnlhdr req;
962 	} u;
963 
964 	assert(h != NULL);
965 	assert(data != NULL);
966 
967 	if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
968 		return -1;
969 
970 	return nfnl_query(h->nfnlh, &u.req.nlh);
971 }
972 
973 /**
974  * nfct_send - send a query to ctnetlink
975  * \param h library handler
976  * \param qt query type
977  * \param data data required to send the query
978  *
979  * Like nfct_query but we do not wait for the reply from ctnetlink.
980  * You can use nfct_send() and nfct_catch() to emulate nfct_query().
981  * This is particularly useful when the socket is non-blocking.
982  *
983  * On error, -1 is returned and errno is explicitely set. On success, 0
984  * is returned.
985  */
nfct_send(struct nfct_handle * h,const enum nf_conntrack_query qt,const void * data)986 int nfct_send(struct nfct_handle *h,
987 	      const enum nf_conntrack_query qt,
988 	      const void *data)
989 {
990 	const size_t size = 4096;	/* enough for now */
991 	union {
992 		char buffer[size];
993 		struct nfnlhdr req;
994 	} u;
995 
996 	assert(h != NULL);
997 	assert(data != NULL);
998 
999 	if (__build_query_ct(h->nfnlssh_ct, qt, data, &u.req, size) == -1)
1000 		return -1;
1001 
1002 	return nfnl_send(h->nfnlh, &u.req.nlh);
1003 }
1004 
1005 
1006 /**
1007  * nfct_catch - catch events
1008  * \param h library handler
1009  *
1010  * This function receives the event from the kernel and it invokes the
1011  * callback that was registered to this handle.
1012  *
1013  * On error, -1 is returned and errno is set appropiately. On success,
1014  * a value greater or equal to 0 is returned indicating the callback
1015  * verdict: NFCT_CB_STOP, NFCT_CB_CONTINUE or NFCT_CB_STOLEN.
1016  *
1017  * Beware that this function also handles expectation events, in case they are
1018  * received through this handle.
1019  */
nfct_catch(struct nfct_handle * h)1020 int nfct_catch(struct nfct_handle *h)
1021 {
1022 	assert(h != NULL);
1023 
1024 	return nfnl_catch(h->nfnlh);
1025 }
1026 
1027 /**
1028  * @}
1029  */
1030 
1031 /**
1032  * \defgroup ct Conntrack object handling
1033  * @{
1034  */
1035 
1036 /**
1037  * nfct_snprintf - print a conntrack object to a buffer
1038  * \param buf buffer used to build the printable conntrack
1039  * \param size size of the buffer
1040  * \param ct pointer to a valid conntrack object
1041  * \param message_type print message type (NFCT_T_UNKNOWN, NFCT_T_NEW,...)
1042  * \param output_type print type (NFCT_O_DEFAULT, NFCT_O_XML, ...)
1043  * \param flags extra flags for the output type (NFCT_OF_LAYER3)
1044  *
1045  * If you are listening to events, probably you want to display the message
1046  * type as well. In that case, set the message type parameter to any of the
1047  * known existing types, ie. NFCT_T_NEW, NFCT_T_UPDATE, NFCT_T_DESTROY.
1048  * If you pass NFCT_T_UNKNOWN, the message type will not be output.
1049  *
1050  * Currently, the output available are:
1051  * 	- NFCT_O_DEFAULT: default /proc-like output
1052  * 	- NFCT_O_XML: XML output
1053  *
1054  * The output flags are:
1055  * 	- NFCT_OF_SHOW_LAYER3: include layer 3 information in the output,
1056  * 	this is *only* required by NFCT_O_DEFAULT.
1057  * 	- NFCT_OF_TIME: display current time.
1058  * 	- NFCT_OF_ID: display the ID number.
1059  * 	- NFCT_OF_TIMESTAMP: display creation and (if exists) deletion time.
1060  *
1061  * To use NFCT_OF_TIMESTAMP, you have to:
1062  * \verbatim
1063  *  $ echo 1 > /proc/sys/net/netfilter/nf_conntrack_timestamp
1064 \endverbatim
1065  * This requires a Linux kernel >= 2.6.38.
1066  *
1067  * Note that NFCT_OF_TIME displays the current time when nfct_snprintf() has
1068  * been called. Thus, it can be used to know when a flow was destroy if you
1069  * print the message just after you receive the destroy event. If you want
1070  * more accurate timestamping, use NFCT_OF_TIMESTAMP.
1071  *
1072  * This function returns the size of the information that _would_ have been
1073  * written to the buffer, even if there was no room for it. Thus, the
1074  * behaviour is similar to snprintf.
1075  */
nfct_snprintf(char * buf,unsigned int size,const struct nf_conntrack * ct,unsigned int msg_type,unsigned int out_type,unsigned int flags)1076 int nfct_snprintf(char *buf,
1077 		  unsigned int size,
1078 		  const struct nf_conntrack *ct,
1079 		  unsigned int msg_type,
1080 		  unsigned int out_type,
1081 		  unsigned int flags)
1082 {
1083 	assert(buf != NULL);
1084 	assert(size > 0);
1085 	assert(ct != NULL);
1086 
1087 	return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, NULL);
1088 }
1089 
1090 /**
1091  * nfct_snprintf_labels - print a bitmask object to a buffer including labels
1092  * \param buf buffer used to build the printable conntrack
1093  * \param size size of the buffer
1094  * \param ct pointer to a valid conntrack object
1095  * \param message_type print message type (NFCT_T_UNKNOWN, NFCT_T_NEW,...)
1096  * \param output_type print type (NFCT_O_DEFAULT, NFCT_O_XML, ...)
1097  * \param flags extra flags for the output type (NFCT_OF_LAYER3)
1098  * \param map nfct_labelmap describing the connlabel translation, or NULL.
1099  *
1100  * When map is NULL, the function is equal to nfct_snprintf().
1101  * Otherwise, if the conntrack object has a connlabel attribute, the active
1102  * labels are translated using the label map and added to the buffer.
1103  */
nfct_snprintf_labels(char * buf,unsigned int size,const struct nf_conntrack * ct,unsigned int msg_type,unsigned int out_type,unsigned int flags,struct nfct_labelmap * map)1104 int nfct_snprintf_labels(char *buf,
1105 			 unsigned int size,
1106 			 const struct nf_conntrack *ct,
1107 			 unsigned int msg_type,
1108 			 unsigned int out_type,
1109 			 unsigned int flags,
1110 			 struct nfct_labelmap *map)
1111 {
1112 	return __snprintf_conntrack(buf, size, ct, msg_type, out_type, flags, map);
1113 }
1114 
1115 /**
1116  * nfct_compare - compare two conntrack objects
1117  * \param ct1 pointer to a valid conntrack object
1118  * \param ct2 pointer to a valid conntrack object
1119  *
1120  * This function only compare attribute set in both objects, ie. if a certain
1121  * attribute is not set in ct1 but it is in ct2, then the value of such
1122  * attribute is not used in the comparison.
1123  *
1124  * If both conntrack object are equal, this function returns 1, otherwise
1125  * 0 is returned.
1126  *
1127  * NOTICE: The use nfct_cmp is preferred.
1128  */
nfct_compare(const struct nf_conntrack * ct1,const struct nf_conntrack * ct2)1129 int nfct_compare(const struct nf_conntrack *ct1,
1130 		 const struct nf_conntrack *ct2)
1131 {
1132 	assert(ct1 != NULL);
1133 	assert(ct2 != NULL);
1134 
1135 	return __compare(ct1, ct2, NFCT_CMP_ALL);
1136 }
1137 
1138 /**
1139  * nfct_cmp - compare two conntrack objects
1140  * \param ct1 pointer to a valid conntrack object
1141  * \param ct2 pointer to a valid conntrack object
1142  * \param flags flags
1143  *
1144  * This function only compare attribute set in both objects, by default
1145  * the comparison is not strict, ie. if a certain attribute is not set in one
1146  * of the objects, then such attribute is not used in the comparison.
1147  * If you want more strict comparisons, you can use the appropriate flags
1148  * to modify this behaviour (see NFCT_CMP_STRICT and NFCT_CMP_MASK).
1149  *
1150  * The available flags are:
1151  *
1152  * 	- NFCT_CMP_STRICT: the compared objects must have the same attributes
1153  * 	and the same values, otherwise it returns that the objects are
1154  * 	different.
1155  * 	- NFCT_CMP_MASK: the first object is used as mask, this means that
1156  * 	if an attribute is present in ct1 but not in ct2, this function
1157  * 	returns that the objects are different.
1158  * 	- NFCT_CMP_ALL: full comparison of both objects
1159  * 	- NFCT_CMP_ORIG: it only compares the source and destination address;
1160  * 	source and destination ports; the layer 3 and 4 protocol numbers
1161  * 	of the original direction; and the id (if present).
1162  * 	- NFCT_CMP_REPL: like NFCT_CMP_REPL but it compares the flow
1163  * 	information that goes in the reply direction.
1164  * 	- NFCT_CMP_TIMEOUT_EQ: timeout(ct1) == timeout(ct2)
1165  * 	- NFCT_CMP_TIMEOUT_GT: timeout(ct1) > timeout(ct2)
1166  * 	- NFCT_CMP_TIMEOUT_LT: timeout(ct1) < timeout(ct2)
1167  * 	- NFCT_CMP_TIMEOUT_GE: timeout(ct1) >= timeout(ct2)
1168  * 	- NFCT_CMP_TIMEOUT_LE: timeout(ct1) <= timeout(ct2)
1169  *
1170  * The status bits comparison is status(ct1) & status(ct2) == status(ct1).
1171  *
1172  * If both conntrack object are equal, this function returns 1, otherwise
1173  * 0 is returned.
1174  */
nfct_cmp(const struct nf_conntrack * ct1,const struct nf_conntrack * ct2,unsigned int flags)1175 int nfct_cmp(const struct nf_conntrack *ct1,
1176 	     const struct nf_conntrack *ct2,
1177 	     unsigned int flags)
1178 {
1179 	assert(ct1 != NULL);
1180 	assert(ct2 != NULL);
1181 
1182 	return __compare(ct1, ct2, flags);
1183 }
1184 
1185 /**
1186  * nfct_copy - copy part of one source object to another
1187  * \param ct1 destination object
1188  * \param ct2 source object
1189  * \param flags flags
1190  *
1191  * This function copies one part of the source object to the target.
1192  * It behaves like clone but:
1193  *
1194  * 1) You have to pass an already allocated space for the target object
1195  * 2) You can copy only a part of the source object to the target
1196  *
1197  * The current supported flags are:
1198  * 	- NFCT_CP_ALL: that copies the object entirely.
1199  * 	- NFCT_CP_ORIG and NFCT_CP_REPL: that can be used to copy the
1200  * 	information that identifies a flow in the original and the reply
1201  * 	direction. This information is usually composed of: source and
1202  * 	destination IP address; source and destination ports; layer 3
1203  * 	and 4 protocol number.
1204  * 	- NFCT_CP_META: that copies the metainformation
1205  * 	(all the attributes >= ATTR_TCP_STATE)
1206  *	- NFCT_CP_OVERRIDE: changes the default behaviour of nfct_copy() since
1207  *	it overrides the destination object. After the copy, the destination
1208  *	is a clone of the origin. This flag provides faster copying.
1209  */
nfct_copy(struct nf_conntrack * ct1,const struct nf_conntrack * ct2,unsigned int flags)1210 void nfct_copy(struct nf_conntrack *ct1,
1211 	       const struct nf_conntrack *ct2,
1212 	       unsigned int flags)
1213 {
1214 	int i;
1215 
1216 	assert(ct1 != NULL);
1217 	assert(ct2 != NULL);
1218 
1219 	if (flags & NFCT_CP_OVERRIDE) {
1220 		__copy_fast(ct1, ct2);
1221 		return;
1222 	}
1223 	if (flags == NFCT_CP_ALL) {
1224 		for (i=0; i<ATTR_MAX; i++) {
1225 			if (test_bit(i, ct2->head.set)) {
1226 				assert(copy_attr_array[i]);
1227 				copy_attr_array[i](ct1, ct2);
1228 				set_bit(i, ct1->head.set);
1229 			}
1230 		}
1231 		return;
1232 	}
1233 
1234 	static const int cp_orig_mask[] = {
1235 		ATTR_ORIG_IPV4_SRC,
1236 		ATTR_ORIG_IPV4_DST,
1237 		ATTR_ORIG_IPV6_SRC,
1238 		ATTR_ORIG_IPV6_DST,
1239 		ATTR_ORIG_PORT_SRC,
1240 		ATTR_ORIG_PORT_DST,
1241 		ATTR_ICMP_TYPE,
1242 		ATTR_ICMP_CODE,
1243 		ATTR_ICMP_ID,
1244 		ATTR_ORIG_L3PROTO,
1245 		ATTR_ORIG_L4PROTO,
1246 	};
1247 	#define __CP_ORIG_MAX sizeof(cp_orig_mask)/sizeof(int)
1248 
1249 	if (flags & NFCT_CP_ORIG) {
1250 		for (i=0; i<__CP_ORIG_MAX; i++) {
1251 			if (test_bit(cp_orig_mask[i], ct2->head.set)) {
1252 				assert(copy_attr_array[i]);
1253 				copy_attr_array[cp_orig_mask[i]](ct1, ct2);
1254 				set_bit(cp_orig_mask[i], ct1->head.set);
1255 			}
1256 		}
1257 	}
1258 
1259 	static const int cp_repl_mask[] = {
1260 		ATTR_REPL_IPV4_SRC,
1261 		ATTR_REPL_IPV4_DST,
1262 		ATTR_REPL_IPV6_SRC,
1263 		ATTR_REPL_IPV6_DST,
1264 		ATTR_REPL_PORT_SRC,
1265 		ATTR_REPL_PORT_DST,
1266 		ATTR_REPL_L3PROTO,
1267 		ATTR_REPL_L4PROTO,
1268 	};
1269 	#define __CP_REPL_MAX sizeof(cp_repl_mask)/sizeof(int)
1270 
1271 	if (flags & NFCT_CP_REPL) {
1272 		for (i=0; i<__CP_REPL_MAX; i++) {
1273 			if (test_bit(cp_repl_mask[i], ct2->head.set)) {
1274 				assert(copy_attr_array[i]);
1275 				copy_attr_array[cp_repl_mask[i]](ct1, ct2);
1276 				set_bit(cp_repl_mask[i], ct1->head.set);
1277 			}
1278 		}
1279 	}
1280 
1281 	if (flags & NFCT_CP_META) {
1282 		for (i=ATTR_TCP_STATE; i<ATTR_MAX; i++) {
1283 			if (test_bit(i, ct2->head.set)) {
1284 				assert(copy_attr_array[i]),
1285 				copy_attr_array[i](ct1, ct2);
1286 				set_bit(i, ct1->head.set);
1287 			}
1288 		}
1289 	}
1290 }
1291 
1292 /**
1293  * nfct_copy_attr - copy an attribute of one source object to another
1294  * \param ct1 destination object
1295  * \param ct2 source object
1296  * \param flags flags
1297  *
1298  * This function copies one attribute (if present) to another object.
1299  */
nfct_copy_attr(struct nf_conntrack * ct1,const struct nf_conntrack * ct2,const enum nf_conntrack_attr type)1300 void nfct_copy_attr(struct nf_conntrack *ct1,
1301 		    const struct nf_conntrack *ct2,
1302 		    const enum nf_conntrack_attr type)
1303 {
1304 	if (test_bit(type, ct2->head.set)) {
1305 		assert(copy_attr_array[type]);
1306 		copy_attr_array[type](ct1, ct2);
1307 		set_bit(type, ct1->head.set);
1308 	}
1309 }
1310 
1311 /**
1312  * @}
1313  */
1314 
1315 /**
1316  * \defgroup bsf Kernel-space filtering for events
1317  *
1318  * @{
1319  */
1320 
1321 /**
1322  * nfct_filter_create - create a filter
1323  *
1324  * This function returns a valid pointer on success, otherwise NULL is
1325  * returned and errno is appropriately set.
1326  */
nfct_filter_create(void)1327 struct nfct_filter *nfct_filter_create(void)
1328 {
1329 	return calloc(sizeof(struct nfct_filter), 1);
1330 }
1331 
1332 /**
1333  * nfct_filter_destroy - destroy a filter
1334  * \param filter filter that we want to destroy
1335  *
1336  * This function releases the memory that is used by the filter object.
1337  * However, please note that this function does *not* detach an already
1338  * attached filter.
1339  */
nfct_filter_destroy(struct nfct_filter * filter)1340 void nfct_filter_destroy(struct nfct_filter *filter)
1341 {
1342 	assert(filter != NULL);
1343 	free(filter);
1344 	filter = NULL;
1345 }
1346 
1347 /**
1348  * nfct_filter_add_attr - add a filter attribute of the filter object
1349  * \param filter filter object that we want to modify
1350  * \param type filter attribute type
1351  * \param value pointer to the value of the filter attribute
1352  *
1353  * Limitations: You can add up to 127 IPv4 addresses and masks for
1354  * NFCT_FILTER_SRC_IPV4 and, similarly, 127 for NFCT_FILTER_DST_IPV4.
1355  */
nfct_filter_add_attr(struct nfct_filter * filter,const enum nfct_filter_attr type,const void * value)1356 void nfct_filter_add_attr(struct nfct_filter *filter,
1357 			  const enum nfct_filter_attr type,
1358 			  const void *value)
1359 {
1360 	assert(filter != NULL);
1361 	assert(value != NULL);
1362 
1363 	if (unlikely(type >= NFCT_FILTER_MAX))
1364 		return;
1365 
1366 	if (filter_attr_array[type]) {
1367 		filter_attr_array[type](filter, value);
1368 		set_bit(type, filter->set);
1369 	}
1370 }
1371 
1372 /**
1373  * nfct_filter_add_attr_u32 - add an u32 filter attribute of the filter object
1374  * \param filter filter object that we want to modify
1375  * \param type filter attribute type
1376  * \param value value of the filter attribute using unsigned int (32 bits).
1377  *
1378  * Limitations: You can add up to 255 protocols which is a reasonable limit.
1379  */
nfct_filter_add_attr_u32(struct nfct_filter * filter,const enum nfct_filter_attr type,uint32_t value)1380 void nfct_filter_add_attr_u32(struct nfct_filter *filter,
1381 			      const enum nfct_filter_attr type,
1382 			      uint32_t value)
1383 {
1384 	nfct_filter_add_attr(filter, type, &value);
1385 }
1386 
1387 /**
1388  * nfct_filter_set_logic - set the filter logic for an attribute type
1389  * \param filter filter object that we want to modify
1390  * \param type filter attribute type
1391  * \param logic filter logic that we want to use
1392  *
1393  * You can only use this function once to set the filtering logic for
1394  * one attribute. You can define two logics: NFCT_FILTER_LOGIC_POSITIVE
1395  * that accept events that match the filter, and NFCT_FILTER_LOGIC_NEGATIVE
1396  * that rejects events that match the filter. Default filtering logic is
1397  * NFCT_FILTER_LOGIC_POSITIVE.
1398  *
1399  * On error, it returns -1 and errno is appropriately set. On success, it
1400  * returns 0.
1401  */
nfct_filter_set_logic(struct nfct_filter * filter,const enum nfct_filter_attr type,const enum nfct_filter_logic logic)1402 int nfct_filter_set_logic(struct nfct_filter *filter,
1403 			  const enum nfct_filter_attr type,
1404 			  const enum nfct_filter_logic logic)
1405 {
1406 	if (unlikely(type >= NFCT_FILTER_MAX)) {
1407 		errno = ENOTSUP;
1408                 return -1;
1409 	}
1410 
1411 	if (filter->logic[type]) {
1412 		errno = EBUSY;
1413 		return -1;
1414 	}
1415 
1416 	filter->logic[type] = logic;
1417 
1418 	return 0;
1419 }
1420 
1421 /**
1422  * nfct_filter_attach - attach a filter to a socket descriptor
1423  * \param fd socket descriptor
1424  * \param filter filter that we want to attach to the socket
1425  *
1426  * This function returns -1 on error and set errno appropriately. If the
1427  * function returns EINVAL probably you have found a bug in it. Please,
1428  * report this.
1429  */
nfct_filter_attach(int fd,struct nfct_filter * filter)1430 int nfct_filter_attach(int fd, struct nfct_filter *filter)
1431 {
1432 	assert(filter != NULL);
1433 
1434 	return __setup_netlink_socket_filter(fd, filter);
1435 }
1436 
1437 /**
1438  * nfct_filter_detach - detach an existing filter
1439  * \param fd socket descriptor
1440  *
1441  * This function returns -1 on error and set errno appropriately.
1442  */
nfct_filter_detach(int fd)1443 int nfct_filter_detach(int fd)
1444 {
1445 	int val = 0;
1446 
1447 	return setsockopt(fd, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val));
1448 }
1449 
1450 /**
1451  * @}
1452  */
1453 
1454 /**
1455  * \defgroup dumpfilter Kernel-space filtering for dumping
1456  *
1457  * @{
1458  */
1459 
1460 /**
1461  * nfct_filter_dump_create - create a dump filter
1462  *
1463  * This function returns a valid pointer on success, otherwise NULL is
1464  * returned and errno is appropriately set.
1465  */
nfct_filter_dump_create(void)1466 struct nfct_filter_dump *nfct_filter_dump_create(void)
1467 {
1468 	return calloc(sizeof(struct nfct_filter_dump), 1);
1469 }
1470 
1471 /**
1472  * nfct_filter_dump_destroy - destroy a dump filter
1473  * \param filter filter that we want to destroy
1474  *
1475  * This function releases the memory that is used by the filter object.
1476  */
nfct_filter_dump_destroy(struct nfct_filter_dump * filter)1477 void nfct_filter_dump_destroy(struct nfct_filter_dump *filter)
1478 {
1479 	assert(filter != NULL);
1480 	free(filter);
1481 	filter = NULL;
1482 }
1483 
1484 /**
1485  * nfct_filter_dump_attr_set - set filter attribute
1486  * \param filter dump filter object that we want to modify
1487  * \param type filter attribute type
1488  * \param value pointer to the value of the filter attribute
1489  */
nfct_filter_dump_set_attr(struct nfct_filter_dump * filter_dump,const enum nfct_filter_dump_attr type,const void * value)1490 void nfct_filter_dump_set_attr(struct nfct_filter_dump *filter_dump,
1491 			       const enum nfct_filter_dump_attr type,
1492 			       const void *value)
1493 {
1494 	assert(filter_dump != NULL);
1495 	assert(value != NULL);
1496 
1497 	if (unlikely(type >= NFCT_FILTER_DUMP_MAX))
1498 		return;
1499 
1500 	if (set_filter_dump_attr_array[type]) {
1501 		set_filter_dump_attr_array[type](filter_dump, value);
1502 		filter_dump->set |= (1 << type);
1503 	}
1504 }
1505 
1506 /**
1507  * nfct_filter_dump_attr_set_u8 - set u8 dump filter attribute
1508  * \param filter dump filter object that we want to modify
1509  * \param type filter attribute type
1510  * \param value value of the filter attribute using unsigned int (32 bits).
1511  */
nfct_filter_dump_set_attr_u8(struct nfct_filter_dump * filter_dump,const enum nfct_filter_dump_attr type,uint8_t value)1512 void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump,
1513 				  const enum nfct_filter_dump_attr type,
1514 				  uint8_t value)
1515 {
1516 	nfct_filter_dump_set_attr(filter_dump, type, &value);
1517 }
1518 
1519 /**
1520  * @}
1521  */
1522 
1523 /**
1524  * \defgroup label Conntrack labels
1525  *
1526  * @{
1527  */
1528 
1529 /**
1530  * nfct_labels_get_path - get name of default config path
1531  *
1532  * returns a pointer to a immutable (static) string containing
1533  * the default connlabel.conf file location.
1534  */
nfct_labels_get_path(void)1535 const char *nfct_labels_get_path(void)
1536 {
1537 	return __labels_get_path();
1538 }
1539 
1540 /**
1541  * nfct_labelmap_get_name - get name of the label bit
1542  *
1543  * \param m label map obtained from nfct_label_open
1544  * \param bit whose name should be returned
1545  *
1546  * returns a pointer to the name associated with the label.
1547  * If no name has been configured, the empty string is returned.
1548  * If bit is out of range, NULL is returned.
1549  */
nfct_labelmap_get_name(struct nfct_labelmap * m,unsigned int bit)1550 const char *nfct_labelmap_get_name(struct nfct_labelmap *m, unsigned int bit)
1551 {
1552 	return __labelmap_get_name(m, bit);
1553 }
1554 
1555 /**
1556  * nfct_labelmap_get_bit - get bit associated with the name
1557  *
1558  * \param h label handle obtained from nfct_labelmap_new
1559  * \param name name of the label
1560  *
1561  * returns the bit associated with the name, or negative value on error.
1562  */
nfct_labelmap_get_bit(struct nfct_labelmap * m,const char * name)1563 int nfct_labelmap_get_bit(struct nfct_labelmap *m, const char *name)
1564 {
1565 	return __labelmap_get_bit(m, name);
1566 }
1567 
1568 /**
1569  * nfct_labelmap_new - create a new label map
1570  *
1571  * \param mapfile the file containing the bit <-> name mapping
1572  *
1573  * If mapfile is NULL, the default mapping file is used.
1574  * returns a new label map, or NULL on error.
1575  */
nfct_labelmap_new(const char * mapfile)1576 struct nfct_labelmap *nfct_labelmap_new(const char *mapfile)
1577 {
1578 	return __labelmap_new(mapfile);
1579 }
1580 
1581 /**
1582  * nfct_labelmap_destroy - destroy nfct_labelmap object
1583  *
1584  * \param map the label object to destroy.
1585  *
1586  * This function releases the memory that is used by the labelmap object.
1587  */
nfct_labelmap_destroy(struct nfct_labelmap * map)1588 void nfct_labelmap_destroy(struct nfct_labelmap *map)
1589 {
1590 	__labelmap_destroy(map);
1591 }
1592 
1593 /**
1594  * @}
1595  */
1596 
1597 /*
1598  * \defgroup bitmask bitmask object
1599  *
1600  * @{
1601  */
1602 
1603 /**
1604  * nfct_bitmask_new - allocate a new bitmask
1605  *
1606  * \param max highest valid bit that can be set/unset.
1607  *
1608  * In case of success, this function returns a valid pointer to a memory blob,
1609  * otherwise NULL is returned and errno is set appropiately.
1610  */
nfct_bitmask_new(unsigned int max)1611 struct nfct_bitmask *nfct_bitmask_new(unsigned int max)
1612 {
1613 	struct nfct_bitmask *b;
1614 	unsigned int bytes, words;
1615 
1616 	if (max > 0xffff)
1617 		return NULL;
1618 
1619 	words = DIV_ROUND_UP(max+1, 32);
1620 	bytes = words * sizeof(b->bits[0]);
1621 
1622 	b = malloc(sizeof(*b) + bytes);
1623 	if (b) {
1624 		memset(b->bits, 0, bytes);
1625 		b->words = words;
1626 	}
1627 	return b;
1628 }
1629 
1630 /*
1631  * nfct_bitmask_clone - duplicate a bitmask object
1632  *
1633  * \param b pointer to the bitmask object to duplicate
1634  *
1635  * returns an identical copy of the bitmask.
1636  */
nfct_bitmask_clone(const struct nfct_bitmask * b)1637 struct nfct_bitmask *nfct_bitmask_clone(const struct nfct_bitmask *b)
1638 {
1639 	unsigned int bytes = b->words * sizeof(b->bits[0]);
1640 	struct nfct_bitmask *copy;
1641 
1642 	bytes += sizeof(*b);
1643 
1644 	copy = malloc(bytes);
1645 	if (copy)
1646 		memcpy(copy, b, bytes);
1647 	return copy;
1648 }
1649 
1650 /*
1651  * nfct_bitmask_set_bit - set bit in the bitmask
1652  *
1653  * \param b pointer to the bitmask object
1654  * \param bit the bit to set
1655  */
nfct_bitmask_set_bit(struct nfct_bitmask * b,unsigned int bit)1656 void nfct_bitmask_set_bit(struct nfct_bitmask *b, unsigned int bit)
1657 {
1658 	unsigned int bits = b->words * 32;
1659 	if (bit < bits)
1660 		set_bit(bit, b->bits);
1661 }
1662 
1663 /*
1664  * nfct_bitmask_test_bit - test if a bit in the bitmask is set
1665  *
1666  * \param b pointer to the bitmask object
1667  * \param bit the bit to test
1668  *
1669  * returns 0 if the bit is not set.
1670  */
nfct_bitmask_test_bit(const struct nfct_bitmask * b,unsigned int bit)1671 int nfct_bitmask_test_bit(const struct nfct_bitmask *b, unsigned int bit)
1672 {
1673 	unsigned int bits = b->words * 32;
1674 	return bit < bits && test_bit(bit, b->bits);
1675 }
1676 
1677 /*
1678  * nfct_bitmask_unset_bit - unset bit in the bitmask
1679  *
1680  * \param b pointer to the bitmask object
1681  * \param bit the bit to clear
1682  */
nfct_bitmask_unset_bit(struct nfct_bitmask * b,unsigned int bit)1683 void nfct_bitmask_unset_bit(struct nfct_bitmask *b, unsigned int bit)
1684 {
1685 	unsigned int bits = b->words * 32;
1686 	if (bit < bits)
1687 		unset_bit(bit, b->bits);
1688 }
1689 
1690 /*
1691  * nfct_bitmask_maxbit - return highest bit that may be set/unset
1692  *
1693  * \param b pointer to the bitmask object
1694  */
nfct_bitmask_maxbit(const struct nfct_bitmask * b)1695 unsigned int nfct_bitmask_maxbit(const struct nfct_bitmask *b)
1696 {
1697 	return (b->words * 32) - 1;
1698 }
1699 
1700 /*
1701  * nfct_bitmask_destroy - destroy bitmask object
1702  *
1703  * \param b pointer to the bitmask object
1704  *
1705  * This function releases the memory that is used by the bitmask object.
1706  *
1707  * If you assign a bitmask object to a nf_conntrack object using
1708  * nfct_set_attr ATTR_CONNLABEL, then the ownership of the bitmask
1709  * object passes on to the nf_conntrack object. The nfct_bitmask object
1710  * will be destroyed when the nf_conntrack object is destroyed.
1711  */
nfct_bitmask_destroy(struct nfct_bitmask * b)1712 void nfct_bitmask_destroy(struct nfct_bitmask *b)
1713 {
1714 	free(b);
1715 }
1716 
1717 /*
1718  * nfct_bitmask_clear - clear a bitmask object
1719  *
1720  * \param b pointer to the bitmask object to clear
1721  */
nfct_bitmask_clear(struct nfct_bitmask * b)1722 void nfct_bitmask_clear(struct nfct_bitmask *b)
1723 {
1724 	unsigned int bytes = b->words * sizeof(b->bits[0]);
1725 	memset(b->bits, 0, bytes);
1726 }
1727 
1728 /*
1729  * nfct_bitmask_equal - compare two bitmask objects
1730  *
1731  * \param b1 pointer to a valid bitmask object
1732  * \param b2 pointer to a valid bitmask object
1733  *
1734  * If both bitmask object are equal, this function returns true, otherwise
1735  * false is returned.
1736  */
nfct_bitmask_equal(const struct nfct_bitmask * b1,const struct nfct_bitmask * b2)1737 bool nfct_bitmask_equal(const struct nfct_bitmask *b1, const struct nfct_bitmask *b2)
1738 {
1739 	if (b1->words != b2->words)
1740 		return false;
1741 
1742 	return memcmp(b1->bits, b2->bits, b1->words * sizeof(b1->bits[0])) == 0;
1743 }
1744 
1745 /**
1746  * @}
1747  */
1748