18a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include <stdio.h>
28a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include <stdlib.h>
38a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include <string.h>
48a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include <errno.h>
58a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include <arpa/inet.h>
68a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
78a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
88a44513648da0c5f5551f96b329cf56b66f5b303pkanwar#include <libnetfilter_conntrack/libnetfilter_conntrack_tcp.h>
98a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
108a44513648da0c5f5551f96b329cf56b66f5b303pkanwar/*
118a44513648da0c5f5551f96b329cf56b66f5b303pkanwar * This example shows how to setup a user-space expectation. This requires
128a44513648da0c5f5551f96b329cf56b66f5b303pkanwar * a Linux kernel >= 2.6.37.
138a44513648da0c5f5551f96b329cf56b66f5b303pkanwar */
148a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
158a44513648da0c5f5551f96b329cf56b66f5b303pkanwarint main(void)
168a44513648da0c5f5551f96b329cf56b66f5b303pkanwar{
178a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	int ret;
188a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	struct nfct_handle *h;
198a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	struct nf_conntrack *master, *expected, *mask;
208a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	struct nf_expect *exp;
218a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
228a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	/*
238a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	 * Step 1: Setup master conntrack
248a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	 */
258a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
268a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	master = nfct_new();
278a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	if (!master) {
288a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		perror("nfct_new");
298a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		exit(EXIT_FAILURE);
308a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	}
318a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
328a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u8(master, ATTR_L3PROTO, AF_INET);
338a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u32(master, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
348a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u32(master, ATTR_IPV4_DST, inet_addr("2.2.2.2"));
358a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
368a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u8(master, ATTR_L4PROTO, IPPROTO_TCP);
378a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u16(master, ATTR_PORT_SRC, htons(1025));
388a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u16(master, ATTR_PORT_DST, htons(21));
398a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
408a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_setobjopt(master, NFCT_SOPT_SETUP_REPLY);
418a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
428a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u8(master, ATTR_TCP_STATE, TCP_CONNTRACK_ESTABLISHED);
438a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u32(master, ATTR_TIMEOUT, 200);
448a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
458a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	h = nfct_open(CONNTRACK, 0);
468a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	if (!h) {
478a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		perror("nfct_open");
488a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		nfct_destroy(master);
498a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		return -1;
508a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	}
518a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
528a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	/*
538a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	 * In a real scenario in which you want to implement an helper in
548a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	 * user-space with NFQUEUE, the master conntrack does not need to
558a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	 * be created, since it should already exist.
568a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	 */
578a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ret = nfct_query(h, NFCT_Q_CREATE, master);
588a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
598a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	printf("TEST: add master conntrack ");
608a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	if (ret == -1)
618a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		printf("(%d)(%s)\n", ret, strerror(errno));
628a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	else
638a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		printf("(OK)\n");
648a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
658a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_close(h);
668a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
678a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	expected = nfct_new();
688a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	if (!expected) {
698a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		perror("nfct_new");
708a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		nfct_destroy(master);
718a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		exit(EXIT_FAILURE);
728a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	}
738a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
748a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET);
758a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u32(expected, ATTR_IPV4_SRC, inet_addr("1.1.1.1"));
768a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u32(expected, ATTR_IPV4_DST, inet_addr("2.2.2.2"));
778a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
788a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u8(expected, ATTR_L4PROTO, IPPROTO_TCP);
798a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u16(expected, ATTR_PORT_SRC, 0);
808a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u16(expected, ATTR_PORT_DST, htons(10241));
818a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
828a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	mask = nfct_new();
838a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	if (!mask) {
848a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		perror("nfct_new");
858a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		nfct_destroy(master);
868a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		nfct_destroy(expected);
878a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		exit(EXIT_FAILURE);
888a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	}
898a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
908a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET);
918a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0xffffffff);
928a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u32(mask, ATTR_IPV4_DST, 0xffffffff);
938a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
948a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u8(mask, ATTR_L4PROTO, IPPROTO_TCP);
958a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0x0000);
968a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_set_attr_u16(mask, ATTR_PORT_DST, 0xffff);
978a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
988a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	/*
998a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	 * Step 2: Setup expectation
1008a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	 */
1018a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1028a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	exp = nfexp_new();
1038a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	if (!exp) {
1048a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		perror("nfexp_new");
1058a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		nfct_destroy(master);
1068a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		nfct_destroy(expected);
1078a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		nfct_destroy(mask);
1088a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		exit(EXIT_FAILURE);
1098a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	}
1108a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1118a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfexp_set_attr(exp, ATTR_EXP_MASTER, master);
1128a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected);
1138a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfexp_set_attr(exp, ATTR_EXP_MASK, mask);
1148a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, 200);
1158a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1168a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_destroy(master);
1178a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_destroy(expected);
1188a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_destroy(mask);
1198a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1208a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	h = nfct_open(EXPECT, 0);
1218a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	if (!h) {
1228a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		perror("nfct_open");
1238a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		return -1;
1248a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	}
1258a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1268a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ret = nfexp_query(h, NFCT_Q_CREATE, exp);
1278a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1288a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	printf("TEST: create expectation ");
1298a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	if (ret == -1)
1308a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		printf("(%d)(%s)\n", ret, strerror(errno));
1318a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	else
1328a44513648da0c5f5551f96b329cf56b66f5b303pkanwar		printf("(OK)\n");
1338a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1348a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	nfct_close(h);
1358a44513648da0c5f5551f96b329cf56b66f5b303pkanwar
1368a44513648da0c5f5551f96b329cf56b66f5b303pkanwar	ret == -1 ? exit(EXIT_FAILURE) : exit(EXIT_SUCCESS);
1378a44513648da0c5f5551f96b329cf56b66f5b303pkanwar}
138