1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <errno.h>
5#include <arpa/inet.h>
6
7#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
8#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>
9
10/*
11 * This example shows how to setup a user-space expectation. This requires
12 * a Linux kernel >= 2.6.37.
13 */
14
15int main(void)
16{
17	int ret;
18	struct nfct_handle *h;
19	struct nf_conntrack *master, *expected, *mask;
20	struct nf_expect *exp;
21
22	/*
23	 * Step 1: Setup master conntrack
24	 */
25
26	master = nfct_new();
27	if (!master) {
28		perror("nfct_new");
29		exit(EXIT_FAILURE);
30	}
31
32	nfct_set_attr_u8(master, ATTR_L3PROTO, AF_INET);
33	nfct_set_attr_u32(master, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
34	nfct_set_attr_u32(master, ATTR_IPV4_DST, inet_addr("2.2.2.2"));
35
36	nfct_set_attr_u8(master, ATTR_L4PROTO, IPPROTO_TCP);
37	nfct_set_attr_u16(master, ATTR_PORT_SRC, htons(1025));
38	nfct_set_attr_u16(master, ATTR_PORT_DST, htons(21));
39
40	nfct_setobjopt(master, NFCT_SOPT_SETUP_REPLY);
41
42	nfct_set_attr_u8(master, ATTR_TCP_STATE, TCP_CONNTRACK_ESTABLISHED);
43	nfct_set_attr_u32(master, ATTR_TIMEOUT, 200);
44
45	h = nfct_open(CONNTRACK, 0);
46	if (!h) {
47		perror("nfct_open");
48		nfct_destroy(master);
49		return -1;
50	}
51
52	/*
53	 * In a real scenario in which you want to implement an helper in
54	 * user-space with NFQUEUE, the master conntrack does not need to
55	 * be created, since it should already exist.
56	 */
57	ret = nfct_query(h, NFCT_Q_CREATE, master);
58
59	printf("TEST: add master conntrack ");
60	if (ret == -1)
61		printf("(%d)(%s)\n", ret, strerror(errno));
62	else
63		printf("(OK)\n");
64
65	nfct_close(h);
66
67	expected = nfct_new();
68	if (!expected) {
69		perror("nfct_new");
70		nfct_destroy(master);
71		exit(EXIT_FAILURE);
72	}
73
74	nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET);
75	nfct_set_attr_u32(expected, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
76	nfct_set_attr_u32(expected, ATTR_IPV4_DST, inet_addr("2.2.2.2"));
77
78	nfct_set_attr_u8(expected, ATTR_L4PROTO, IPPROTO_TCP);
79	nfct_set_attr_u16(expected, ATTR_PORT_SRC, 0);
80	nfct_set_attr_u16(expected, ATTR_PORT_DST, htons(10241));
81
82	mask = nfct_new();
83	if (!mask) {
84		perror("nfct_new");
85		nfct_destroy(master);
86		nfct_destroy(expected);
87		exit(EXIT_FAILURE);
88	}
89
90	nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET);
91	nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0xffffffff);
92	nfct_set_attr_u32(mask, ATTR_IPV4_DST, 0xffffffff);
93
94	nfct_set_attr_u8(mask, ATTR_L4PROTO, IPPROTO_TCP);
95	nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0x0000);
96	nfct_set_attr_u16(mask, ATTR_PORT_DST, 0xffff);
97
98	/*
99	 * Step 2: Setup expectation
100	 */
101
102	exp = nfexp_new();
103	if (!exp) {
104		perror("nfexp_new");
105		nfct_destroy(master);
106		nfct_destroy(expected);
107		nfct_destroy(mask);
108		exit(EXIT_FAILURE);
109	}
110
111	nfexp_set_attr(exp, ATTR_EXP_MASTER, master);
112	nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected);
113	nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
114	nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, 200);
115
116	nfct_destroy(master);
117	nfct_destroy(expected);
118	nfct_destroy(mask);
119
120	h = nfct_open(EXPECT, 0);
121	if (!h) {
122		perror("nfct_open");
123		return -1;
124	}
125
126	ret = nfexp_query(h, NFCT_Q_CREATE, exp);
127
128	printf("TEST: create expectation ");
129	if (ret == -1)
130		printf("(%d)(%s)\n", ret, strerror(errno));
131	else
132		printf("(OK)\n");
133
134	nfct_close(h);
135
136	ret == -1 ? exit(EXIT_FAILURE) : exit(EXIT_SUCCESS);
137}
138