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