示例#1
0
/* So, this packet has hit the connection tracking matching code.
   Mangle it, and change the expectation to match the new version. */
static unsigned int
nf_nat_rpc(struct pkt_buff *pkt, int dir, struct nf_expect *exp,
	   uint8_t proto, uint32_t *port_ptr)
{
	const struct nf_conntrack *expected;
	struct nf_conntrack *nat_tuple;
	uint16_t initial_port, port;

	expected = nfexp_get_attr(exp, ATTR_EXP_EXPECTED);

	nat_tuple = nfct_new();
	if (nat_tuple == NULL)
		return NF_ACCEPT;

	initial_port = nfct_get_attr_u16(expected, ATTR_PORT_DST);

	nfexp_set_attr_u32(exp, ATTR_EXP_NAT_DIR, !dir);

	/* libnetfilter_conntrack needs this */
	nfct_set_attr_u8(nat_tuple, ATTR_L3PROTO, AF_INET);
	nfct_set_attr_u32(nat_tuple, ATTR_IPV4_SRC, 0);
	nfct_set_attr_u32(nat_tuple, ATTR_IPV4_DST, 0);
	nfct_set_attr_u8(nat_tuple, ATTR_L4PROTO, proto);
	nfct_set_attr_u16(nat_tuple, ATTR_PORT_DST, 0);

	/* When you see the packet, we need to NAT it the same as the
	 * this one. */
	nfexp_set_attr(exp, ATTR_EXP_FN, "nat-follow-master");

	/* Try to get same port: if not, try to change it. */
	for (port = ntohs(initial_port); port != 0; port++) {
		int ret;

		nfct_set_attr_u16(nat_tuple, ATTR_PORT_SRC, htons(port));
		nfexp_set_attr(exp, ATTR_EXP_NAT_TUPLE, nat_tuple);

		ret = cthelper_add_expect(exp);
		if (ret == 0)
			break;
		else if (ret != -EBUSY) {
			port = 0;
			break;
		}
	}
	nfct_destroy(nat_tuple);

	if (port == 0)
		return NF_DROP;

	*port_ptr = htonl(port);

	return NF_ACCEPT;
}
int main(void)
{
	int ret, i;
	struct nf_conntrack *ct, *ct2, *tmp;
	struct nf_expect *exp, *tmp_exp;
	char data[256];
	const char *val;
	int status;
	struct nfct_bitmask *b, *b2;

	srand(time(NULL));

	/* initialize fake data for testing purposes */
	for (i=0; i<sizeof(data); i++)
		data[i] = 0x01;

	ct = nfct_new();
	if (!ct) {
		perror("nfct_new");
		return 0;
	}
	tmp = nfct_new();
	if (!tmp) {
		perror("nfct_new");
		return 0;
	}

	printf("== test set API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_MAX; i++)
			nfct_set_attr(ct, i, data);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	b = nfct_bitmask_new(rand() & 0xffff);
	assert(b);
	b2 = nfct_bitmask_new(rand() & 0xffff);
	assert(b2);

	for (i=0; i<ATTR_MAX; i++) {
		switch (i) {
		case ATTR_CONNLABELS:
			nfct_set_attr(ct, i, b);
			break;
		case ATTR_CONNLABELS_MASK:
			nfct_set_attr(ct, i, b2);
			break;
		default:
			nfct_set_attr(ct, i, data);
			break;
		}
	}

	printf("== test get API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_MAX; i++)
			nfct_get_attr(ct, i);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	printf("== validate set API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_MAX; i++) {
			if (attr_is_readonly(i))
				continue;
			switch(i) {
			/* These attributes require special handling */
			case ATTR_HELPER_INFO:
				nfct_set_attr_l(ct, i, data, sizeof(data));
				break;
			case ATTR_CONNLABELS:
			case ATTR_CONNLABELS_MASK:
				/* already set above */
				break;
			default:
				data[0] = (uint8_t) i;
				nfct_set_attr(ct, i, data);
			}
			val = nfct_get_attr(ct, i);
			switch (i) {
			case ATTR_CONNLABELS:
				assert((void *) val == b);
				continue;
			case ATTR_CONNLABELS_MASK:
				assert((void *) val == b2);
				continue;
			}

			if (val[0] != data[0]) {
				printf("ERROR: set/get operations don't match "
				       "for attribute %d (%x != %x)\n",
					i, val[0], data[0]);
			}
		}
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	printf("== test copy API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_MAX; i++)
			nfct_copy_attr(tmp, ct, i);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	ret = fork();
	if (ret == 0) {
		test_nfct_cmp_api(tmp, ct);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	exp = nfexp_new();
	if (!exp) {
		perror("nfexp_new");
		return 0;
	}
	tmp_exp = nfexp_new();
	if (!tmp_exp) {
		perror("nfexp_new");
		return 0;
	}

	printf("== test expect set API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_EXP_MAX; i++)
			nfexp_set_attr(exp, i, data);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	for (i=0; i<ATTR_EXP_MAX; i++)
		nfexp_set_attr(exp, i, data);

	printf("== test expect get API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_EXP_MAX; i++)
			nfexp_get_attr(exp, i);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	printf("== validate expect set API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_EXP_MAX; i++) {
			data[0] = (uint8_t) i;
			nfexp_set_attr(exp, i, data);
			val = nfexp_get_attr(exp, i);
			if (val[0] != data[0]) {
				printf("ERROR: set/get operations don't match "
				       "for attribute %d (%x != %x)\n",
					i, val[0], data[0]);
			}
		}
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	ret = fork();
	if (ret == 0) {
		test_nfexp_cmp_api(tmp_exp, exp);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	ct2 = nfct_new();
	if (!ct2) {
		perror("nfct_new");
		return 0;
	}

	printf("== test set grp API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_GRP_MAX; i++)
			nfct_set_attr_grp(ct2, i, data);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	for (i=0; i<ATTR_GRP_MAX; i++)
		nfct_set_attr_grp(ct2, i, data);

	printf("== test get grp API ==\n");
	ret = fork();
	if (ret == 0) {
		char buf[32]; /* IPv6 group address is 16 bytes * 2 */

		for (i=0; i<ATTR_GRP_MAX; i++)
			nfct_get_attr_grp(ct2, i, buf);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	printf("== validate set grp API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_GRP_MAX; i++) {
			char buf[32]; /* IPv6 group address is 16 bytes */

			data[0] = (uint8_t) i;
			nfct_set_attr_grp(ct2, i, data);
			nfct_get_attr_grp(ct2, i, buf);
			/* These attributes cannot be set, ignore them. */
			switch(i) {
			case ATTR_GRP_ORIG_COUNTERS:
			case ATTR_GRP_REPL_COUNTERS:
			case ATTR_GRP_ORIG_ADDR_SRC:
			case ATTR_GRP_ORIG_ADDR_DST:
			case ATTR_GRP_REPL_ADDR_SRC:
			case ATTR_GRP_REPL_ADDR_DST:
				continue;
			}
			if (buf[0] != data[0]) {
				printf("ERROR: set/get operations don't match "
				       "for attribute %d (%x != %x)\n",
					i, buf[0], data[0]);
			}
		}
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	nfct_destroy(ct2);
	printf("== destroy cloned ct entry ==\n");
	nfct_destroy(ct);
	nfct_destroy(tmp);
	nfexp_destroy(exp);
	nfexp_destroy(tmp_exp);

	printf("OK\n");

	test_nfct_bitmask();

	return EXIT_SUCCESS;
}
示例#3
0
/**
 * nfexp_get_attr_u32 - get attribute of unsigned 32-bits long
 * \param exp pointer to a valid expectation
 * \param type attribute type
 *
 * Returns the value of the requested attribute, if the attribute is not 
 * set, 0 is returned. In order to check if the attribute is set or not,
 * use nfexp_attr_is_set.
 */
uint32_t nfexp_get_attr_u32(const struct nf_expect *exp,
			    const enum nf_expect_attr type)
{
	const uint32_t *ret = nfexp_get_attr(exp, type);
	return ret == NULL ? 0 : *ret;
}
int main(void)
{
	int ret, i;
	struct nf_conntrack *ct, *ct2, *tmp;
	struct nf_expect *exp, *tmp_exp;
	char data[256];
	const char *val;
	int status;

	/* initialize fake data for testing purposes */
	for (i=0; i<sizeof(data); i++)
		data[i] = 0x01;

	ct = nfct_new();
	if (!ct) {
		perror("nfct_new");
		return 0;
	}
	tmp = nfct_new();
	if (!tmp) {
		perror("nfct_new");
		return 0;
	}

	printf("== test set API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_MAX; i++)
			nfct_set_attr(ct, i, data);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	for (i=0; i<ATTR_MAX; i++)
		nfct_set_attr(ct, i, data);

	printf("== test get API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_MAX; i++)
			nfct_get_attr(ct, i);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	printf("== validate set API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_MAX; i++) {
			/* These attributes cannot be set, ignore them. */
			switch(i) {
			case ATTR_ORIG_COUNTER_PACKETS:
			case ATTR_REPL_COUNTER_PACKETS:
			case ATTR_ORIG_COUNTER_BYTES:
			case ATTR_REPL_COUNTER_BYTES:
			case ATTR_USE:
			case ATTR_SECCTX:
			case ATTR_TIMESTAMP_START:
			case ATTR_TIMESTAMP_STOP:
				continue;
			/* These attributes require special handling */
			case ATTR_HELPER_INFO:
				nfct_set_attr_l(ct, i, data, sizeof(data));
				break;
			default:
				data[0] = (uint8_t) i;
				nfct_set_attr(ct, i, data);
			}
			val = nfct_get_attr(ct, i);

			if (val[0] != data[0]) {
				printf("ERROR: set/get operations don't match "
				       "for attribute %d (%x != %x)\n",
					i, val[0], data[0]);
			}
		}
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	printf("== test copy API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_MAX; i++)
			nfct_copy_attr(tmp, ct, i);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	printf("== test cmp API ==\n");
	ret = fork();
	if (ret == 0) {
		nfct_cmp(tmp, ct, NFCT_CMP_ALL);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	exp = nfexp_new();
	if (!exp) {
		perror("nfexp_new");
		return 0;
	}
	tmp_exp = nfexp_new();
	if (!tmp_exp) {
		perror("nfexp_new");
		return 0;
	}

	printf("== test expect set API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_EXP_MAX; i++)
			nfexp_set_attr(exp, i, data);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	for (i=0; i<ATTR_EXP_MAX; i++)
		nfexp_set_attr(exp, i, data);

	printf("== test expect get API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_EXP_MAX; i++)
			nfexp_get_attr(exp, i);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	printf("== validate expect set API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_EXP_MAX; i++) {
			data[0] = (uint8_t) i;
			nfexp_set_attr(exp, i, data);
			val = nfexp_get_attr(exp, i);
			if (val[0] != data[0]) {
				printf("ERROR: set/get operations don't match "
				       "for attribute %d (%x != %x)\n",
					i, val[0], data[0]);
			}
		}
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	/* XXX: missing nfexp_copy API. */
	memcpy(tmp_exp, exp, nfexp_maxsize());

	printf("== test expect cmp API ==\n");
	ret = fork();
	if (ret == 0) {
		nfexp_cmp(tmp_exp, exp, 0);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	ct2 = nfct_clone(ct);
	assert(ct2);
	assert(nfct_cmp(ct, ct2, NFCT_CMP_ALL) == 1);
	nfct_destroy(ct2);

	ct2 = nfct_new();
	if (!ct2) {
		perror("nfct_new");
		return 0;
	}

	printf("== test set grp API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_GRP_MAX; i++)
			nfct_set_attr_grp(ct2, i, data);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	for (i=0; i<ATTR_GRP_MAX; i++)
		nfct_set_attr_grp(ct2, i, data);

	printf("== test get grp API ==\n");
	ret = fork();
	if (ret == 0) {
		char buf[32]; /* IPv6 group address is 16 bytes * 2 */

		for (i=0; i<ATTR_GRP_MAX; i++)
			nfct_get_attr_grp(ct2, i, buf);
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	printf("== validate set grp API ==\n");
	ret = fork();
	if (ret == 0) {
		for (i=0; i<ATTR_GRP_MAX; i++) {
			char buf[32]; /* IPv6 group address is 16 bytes */

			data[0] = (uint8_t) i;
			nfct_set_attr_grp(ct2, i, data);
			nfct_get_attr_grp(ct2, i, buf);
			/* These attributes cannot be set, ignore them. */
			switch(i) {
			case ATTR_GRP_ORIG_COUNTERS:
			case ATTR_GRP_REPL_COUNTERS:
			case ATTR_GRP_ORIG_ADDR_SRC:
			case ATTR_GRP_ORIG_ADDR_DST:
			case ATTR_GRP_REPL_ADDR_SRC:
			case ATTR_GRP_REPL_ADDR_DST:
				continue;
			}
			if (buf[0] != data[0]) {
				printf("ERROR: set/get operations don't match "
				       "for attribute %d (%x != %x)\n",
					i, buf[0], data[0]);
			}
		}
		exit(0);
	} else {
		wait(&status);
		eval_sigterm(status);
	}

	nfct_destroy(ct2);
	printf("== destroy cloned ct entry ==\n");
	nfct_destroy(ct);
	nfct_destroy(tmp);
	nfexp_destroy(exp);
	nfexp_destroy(tmp_exp);
	printf("OK\n");

	return EXIT_SUCCESS;
}