npf_rule_test.c revision 1.10.2.1
11.10.2.1Stls/*	$NetBSD: npf_rule_test.c,v 1.10.2.1 2014/08/10 07:00:01 tls Exp $	*/
21.1Srmind
31.1Srmind/*
41.1Srmind * NPF ruleset test.
51.1Srmind *
61.1Srmind * Public Domain.
71.1Srmind */
81.1Srmind
91.1Srmind#include <sys/types.h>
101.1Srmind
111.1Srmind#include "npf_impl.h"
121.1Srmind#include "npf_test.h"
131.1Srmind
141.1Srmind#define	RESULT_PASS	0
151.1Srmind#define	RESULT_BLOCK	ENETUNREACH
161.1Srmind
171.1Srmindstatic const struct test_case {
181.1Srmind	const char *	src;
191.1Srmind	const char *	dst;
201.1Srmind	const char *	ifname;
211.1Srmind	int		di;
221.1Srmind	int		stateful_ret;
231.1Srmind	int		ret;
241.1Srmind} test_cases[] = {
251.1Srmind
261.1Srmind	/* Stateful pass. */
271.1Srmind	{
281.1Srmind		.src = "10.1.1.1",		.dst = "10.1.1.2",
291.1Srmind		.ifname = IFNAME_INT,		.di = PFIL_OUT,
301.1Srmind		.stateful_ret = RESULT_PASS,	.ret = RESULT_PASS
311.1Srmind	},
321.1Srmind	{
331.1Srmind		.src = "10.1.1.2",		.dst = "10.1.1.1",
341.1Srmind		.ifname = IFNAME_INT,		.di = PFIL_IN,
351.1Srmind		.stateful_ret = RESULT_PASS,	.ret = RESULT_BLOCK
361.1Srmind	},
371.1Srmind
381.1Srmind	/* Pass forwards stream only. */
391.1Srmind	{
401.1Srmind		.src = "10.1.1.1",		.dst = "10.1.1.3",
411.1Srmind		.ifname = IFNAME_INT,		.di = PFIL_OUT,
421.1Srmind		.stateful_ret = RESULT_PASS,	.ret = RESULT_PASS
431.1Srmind	},
441.1Srmind	{
451.1Srmind		.src = "10.1.1.3",		.dst = "10.1.1.1",
461.1Srmind		.ifname = IFNAME_INT,		.di = PFIL_IN,
471.1Srmind		.stateful_ret = RESULT_BLOCK,	.ret = RESULT_BLOCK
481.1Srmind	},
491.1Srmind
501.1Srmind	/* Block. */
511.1Srmind	{	.src = "10.1.1.1",		.dst = "10.1.1.4",
521.1Srmind		.ifname = IFNAME_INT,		.di = PFIL_OUT,
531.1Srmind		.stateful_ret = RESULT_BLOCK,	.ret = RESULT_BLOCK
541.1Srmind	},
551.1Srmind
561.1Srmind};
571.1Srmind
581.1Srmindstatic struct mbuf *
591.1Srmindfill_packet(const struct test_case *t)
601.1Srmind{
611.1Srmind	struct mbuf *m;
621.1Srmind	struct ip *ip;
631.1Srmind	struct udphdr *uh;
641.1Srmind
651.1Srmind	m = mbuf_construct(IPPROTO_UDP);
661.1Srmind	uh = mbuf_return_hdrs(m, false, &ip);
671.1Srmind	ip->ip_src.s_addr = inet_addr(t->src);
681.1Srmind	ip->ip_dst.s_addr = inet_addr(t->dst);
691.1Srmind	uh->uh_sport = htons(9000);
701.1Srmind	uh->uh_dport = htons(9000);
711.1Srmind	return m;
721.1Srmind}
731.1Srmind
741.1Srmindstatic int
751.1Srmindnpf_rule_raw_test(bool verbose, struct mbuf *m, ifnet_t *ifp, int di)
761.1Srmind{
771.1Srmind	npf_cache_t npc = { .npc_info = 0 };
781.3Srmind	nbuf_t nbuf;
791.1Srmind	npf_rule_t *rl;
801.1Srmind	int retfl, error;
811.1Srmind
821.3Srmind	nbuf_init(&nbuf, m, ifp);
831.10.2.1Stls	npc.npc_nbuf = &nbuf;
841.10.2.1Stls	npf_cache_all(&npc);
851.3Srmind
861.4Srmind	int slock = npf_config_read_enter();
871.10.2.1Stls	rl = npf_ruleset_inspect(&npc, npf_config_ruleset(),
881.3Srmind	    di, NPF_LAYER_3);
891.1Srmind	if (rl) {
901.4Srmind		error = npf_rule_conclude(rl, &retfl);
911.1Srmind	} else {
921.1Srmind		error = ENOENT;
931.1Srmind	}
941.4Srmind	npf_config_read_exit(slock);
951.1Srmind	return error;
961.1Srmind}
971.1Srmind
981.4Srmindstatic int
991.8Srmindnpf_test_case(u_int i, bool verbose)
1001.4Srmind{
1011.8Srmind	const struct test_case *t = &test_cases[i];
1021.4Srmind	ifnet_t *ifp = ifunit(t->ifname);
1031.4Srmind	int error;
1041.4Srmind
1051.4Srmind	struct mbuf *m = fill_packet(t);
1061.4Srmind	error = npf_rule_raw_test(verbose, m, ifp, t->di);
1071.4Srmind	m_freem(m);
1081.4Srmind	return error;
1091.4Srmind}
1101.4Srmind
1111.4Srmindstatic npf_rule_t *
1121.4Srmindnpf_blockall_rule(void)
1131.4Srmind{
1141.4Srmind	prop_dictionary_t rldict;
1151.4Srmind
1161.4Srmind	rldict = prop_dictionary_create();
1171.4Srmind	prop_dictionary_set_uint32(rldict, "attributes",
1181.7Srmind	    NPF_RULE_IN | NPF_RULE_OUT | NPF_RULE_DYNAMIC);
1191.4Srmind	return npf_rule_alloc(rldict);
1201.4Srmind}
1211.4Srmind
1221.1Srmindbool
1231.1Srmindnpf_rule_test(bool verbose)
1241.1Srmind{
1251.4Srmind	npf_ruleset_t *rlset;
1261.4Srmind	npf_rule_t *rl;
1271.2Srmind	bool fail = false;
1281.6Srmind	uint64_t id;
1291.4Srmind	int error;
1301.2Srmind
1311.1Srmind	for (unsigned i = 0; i < __arraycount(test_cases); i++) {
1321.1Srmind		const struct test_case *t = &test_cases[i];
1331.1Srmind		ifnet_t *ifp = ifunit(t->ifname);
1341.4Srmind		int serror;
1351.1Srmind
1361.1Srmind		if (ifp == NULL) {
1371.1Srmind			printf("Interface %s is not configured.\n", t->ifname);
1381.1Srmind			return false;
1391.1Srmind		}
1401.1Srmind
1411.2Srmind		struct mbuf *m = fill_packet(t);
1421.1Srmind		error = npf_rule_raw_test(verbose, m, ifp, t->di);
1431.1Srmind		serror = npf_packet_handler(NULL, &m, ifp, t->di);
1441.1Srmind
1451.1Srmind		if (m) {
1461.1Srmind			m_freem(m);
1471.1Srmind		}
1481.1Srmind
1491.1Srmind		if (verbose) {
1501.1Srmind			printf("Rule test %d, expected %d (stateful) and %d \n"
1511.1Srmind			    "-> returned %d and %d.\n",
1521.1Srmind			    i + 1, t->stateful_ret, t->ret, serror, error);
1531.1Srmind		}
1541.2Srmind		fail |= (serror != t->stateful_ret || error != t->ret);
1551.1Srmind	}
1561.4Srmind
1571.8Srmind	/*
1581.8Srmind	 * Test dynamic NPF rules.
1591.8Srmind	 */
1601.8Srmind
1611.8Srmind	error = npf_test_case(0, verbose);
1621.4Srmind	assert(error == RESULT_PASS);
1631.4Srmind
1641.4Srmind	npf_config_enter();
1651.4Srmind	rlset = npf_config_ruleset();
1661.4Srmind
1671.4Srmind	rl = npf_blockall_rule();
1681.4Srmind	error = npf_ruleset_add(rlset, "test-rules", rl);
1691.4Srmind	fail |= error != 0;
1701.4Srmind
1711.8Srmind	error = npf_test_case(0, verbose);
1721.4Srmind	fail |= (error != RESULT_BLOCK);
1731.4Srmind
1741.6Srmind	id = npf_rule_getid(rl);
1751.6Srmind	error = npf_ruleset_remove(rlset, "test-rules", id);
1761.5Srmind	fail |= error != 0;
1771.4Srmind
1781.4Srmind	npf_config_exit();
1791.4Srmind
1801.8Srmind	error = npf_test_case(0, verbose);
1811.4Srmind	fail |= (error != RESULT_PASS);
1821.4Srmind
1831.2Srmind	return !fail;
1841.1Srmind}
185