1/* $NetBSD: npf_processor_test.c,v 1.1.4.4 2012/11/18 21:48:56 riz Exp $ */ 2 3/* 4 * NPF n-code processor test. 5 * 6 * Public Domain. 7 */ 8 9#include <sys/types.h> 10#include <sys/endian.h> 11 12#include "npf_impl.h" 13#include "npf_ncode.h" 14#include "npf_test.h" 15 16#if BYTE_ORDER == LITTLE_ENDIAN 17#define IP4(a, b, c, d) ((a << 0) | (b << 8) | (c << 16) | (d << 24)) 18#elif BYTE_ORDER == BIG_ENDIAN 19#define IP4(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | (d << 0)) 20#endif 21 22#define PORTS(a, b) ((htons(a) << 16) | htons(b)) 23 24static const uint32_t nc_match[] = { 25 NPF_OPCODE_CMP, NPF_LAYER_3, 0, 26 NPF_OPCODE_BEQ, 0x0c, 27 NPF_OPCODE_ETHER, 0x00, 0x00, htons(ETHERTYPE_IP), 28 NPF_OPCODE_BEQ, 0x04, 29 NPF_OPCODE_RET, 0xff, 30 NPF_OPCODE_ADVR, 3, 31 NPF_OPCODE_IP4MASK, 0x01, IP4(192,168,2,0), 24, 32 NPF_OPCODE_BEQ, 0x04, 33 NPF_OPCODE_RET, 0xff, 34 NPF_OPCODE_TCP_PORTS, 0x00, PORTS(80, 80), 35 NPF_OPCODE_BEQ, 0x04, 36 NPF_OPCODE_RET, 0xff, 37 NPF_OPCODE_RET, 0x00 38}; 39 40static const uint32_t nc_nmatch[] = { 41 NPF_OPCODE_CMP, NPF_LAYER_3, 0, 42 NPF_OPCODE_BEQ, 0x0c, 43 NPF_OPCODE_ETHER, 0x00, 0x00, htons(ETHERTYPE_IP), 44 NPF_OPCODE_BEQ, 0x04, 45 NPF_OPCODE_RET, 0xff, 46 NPF_OPCODE_ADVR, 3, 47 NPF_OPCODE_IP4MASK, 0x01, IP4(192,168,2,1), 32, 48 NPF_OPCODE_BEQ, 0x04, 49 NPF_OPCODE_RET, 0xff, 50 NPF_OPCODE_RET, 0x00 51}; 52 53static const uint32_t nc_rmatch[] = { 54 NPF_OPCODE_MOVE, offsetof(struct ip, ip_src), 1, 55 NPF_OPCODE_ADVR, 1, 56 NPF_OPCODE_LW, sizeof(in_addr_t), 0, 57 NPF_OPCODE_CMP, IP4(192,168,2,100), 0, 58 NPF_OPCODE_BEQ, 0x04, 59 NPF_OPCODE_RET, 0xff, 60 NPF_OPCODE_MOVE, sizeof(struct ip) - offsetof(struct ip, ip_src) 61 + offsetof(struct tcphdr, th_sport), 1, 62 NPF_OPCODE_ADVR, 1, 63 NPF_OPCODE_LW, 2 * sizeof(in_port_t), 0, 64 NPF_OPCODE_CMP, htonl((15000 << 16) | 80), 0, 65 NPF_OPCODE_BEQ, 0x04, 66 NPF_OPCODE_RET, 0xff, 67 NPF_OPCODE_RET, 0x01 68}; 69 70static const uint32_t nc_inval[] = { 71 NPF_OPCODE_BEQ, 0x05, 72 NPF_OPCODE_RET, 0xff, 73 NPF_OPCODE_RET, 0x01 74}; 75 76static const uint32_t nc_match6[] = { 77 NPF_OPCODE_IP6MASK, 0x01, htonl(0xfe80 << 16), 0x0, 0x0, 0x0, 10, 78 NPF_OPCODE_BEQ, 0x04, 79 NPF_OPCODE_RET, 0xff, 80 NPF_OPCODE_TCP_PORTS, 0x00, PORTS(80, 80), 81 NPF_OPCODE_BEQ, 0x04, 82 NPF_OPCODE_RET, 0xff, 83 NPF_OPCODE_RET, 0x00 84}; 85 86static struct mbuf * 87fill_packet(int proto, bool ether) 88{ 89 struct mbuf *m; 90 struct ip *ip; 91 struct tcphdr *th; 92 93 if (ether) { 94 m = mbuf_construct_ether(IPPROTO_TCP); 95 } else { 96 m = mbuf_construct(IPPROTO_TCP); 97 } 98 th = mbuf_return_hdrs(m, ether, &ip); 99 ip->ip_src.s_addr = inet_addr("192.168.2.100"); 100 ip->ip_dst.s_addr = inet_addr("10.0.0.1"); 101 th->th_sport = htons(15000); 102 th->th_dport = htons(80); 103 return m; 104} 105 106static struct mbuf * 107fill_packet6(int proto) 108{ 109 uint16_t src[] = { 110 htons(0xfe80), 0x0, 0x0, 0x0, 111 htons(0x2a0), htons(0xc0ff), htons(0xfe10), htons(0x1234) 112 }; 113 uint16_t dst[] = { 114 htons(0xfe80), 0x0, 0x0, 0x0, 115 htons(0x2a0), htons(0xc0ff), htons(0xfe10), htons(0x1111) 116 }; 117 struct mbuf *m; 118 struct ip6_hdr *ip; 119 struct tcphdr *th; 120 121 m = mbuf_construct6(proto); 122 (void)mbuf_return_hdrs(m, false, (struct ip **)&ip); 123 memcpy(&ip->ip6_src, src, sizeof(ip->ip6_src)); 124 memcpy(&ip->ip6_dst, dst, sizeof(ip->ip6_src)); 125 126 th = (void *)(ip + 1); 127 th->th_sport = htons(15000); 128 th->th_dport = htons(80); 129 return m; 130} 131 132static bool 133retcode_fail_p(const char *msg, bool verbose, int ret, int expected) 134{ 135 bool fail = (ret != expected); 136 137 if (verbose) { 138 printf("%-25s\t%-4d == %4d\t-> %s\n", 139 msg, ret, expected, fail ? "fail" : "ok"); 140 } 141 return fail; 142} 143 144static void 145npf_nc_cachetest(struct mbuf *m, npf_cache_t *npc, nbuf_t *nbuf) 146{ 147 const void *dummy_ifp = (void *)0xdeadbeef; 148 149 nbuf_init(nbuf, m, dummy_ifp); 150 memset(npc, 0, sizeof(npf_cache_t)); 151 npf_cache_all(npc, nbuf); 152} 153 154bool 155npf_processor_test(bool verbose) 156{ 157 npf_cache_t npc; 158 struct mbuf *m; 159 nbuf_t nbuf; 160 int errat, ret; 161 bool fail = false; 162 163#if 0 164 /* Layer 2 (Ethernet + IP + TCP). */ 165 ret = npf_ncode_validate(nc_match, sizeof(nc_match), &errat); 166 fail |= retcode_fail_p("Ether validation", verbose, ret, 0); 167 168 m = fill_packet(IPPROTO_TCP, true); 169 npf_nc_cachetest(m, &npc, &nbuf); 170 ret = npf_ncode_process(&npc, nc_match, &nbuf, NPF_LAYER_2); 171 fail |= retcode_fail_p("Ether", verbose, ret, 0); 172 m_freem(m); 173#endif 174 175 /* Layer 3 (IP + TCP). */ 176 m = fill_packet(IPPROTO_TCP, false); 177 npf_nc_cachetest(m, &npc, &nbuf); 178 ret = npf_ncode_process(&npc, nc_match, &nbuf, NPF_LAYER_3); 179 fail |= retcode_fail_p("IPv4 mask 1", verbose, ret, 0); 180 181 /* Non-matching IPv4 case. */ 182 ret = npf_ncode_validate(nc_nmatch, sizeof(nc_nmatch), &errat); 183 fail |= retcode_fail_p("IPv4 mask 2 validation", verbose, ret, 0); 184 185 npf_nc_cachetest(m, &npc, &nbuf); 186 ret = npf_ncode_process(&npc, nc_nmatch, &nbuf, NPF_LAYER_3); 187 fail |= retcode_fail_p("IPv4 mask 2", verbose, ret, 255); 188 189 /* Invalid n-code case. */ 190 ret = npf_ncode_validate(nc_inval, sizeof(nc_inval), &errat); 191 fail |= retcode_fail_p("Invalid n-code", verbose, ret, NPF_ERR_JUMP); 192 193 /* RISC-like insns. */ 194 ret = npf_ncode_validate(nc_rmatch, sizeof(nc_rmatch), &errat); 195 fail |= retcode_fail_p("RISC-like n-code validation", verbose, ret, 0); 196 197 npf_nc_cachetest(m, &npc, &nbuf); 198 ret = npf_ncode_process(&npc, nc_rmatch, &nbuf, NPF_LAYER_3); 199 fail |= retcode_fail_p("RISC-like n-code", verbose, ret, 1); 200 m_freem(m); 201 202 /* IPv6 matching. */ 203 ret = npf_ncode_validate(nc_match6, sizeof(nc_match6), &errat); 204 fail |= retcode_fail_p("IPv6 mask validation", verbose, ret, 0); 205 206 m = fill_packet6(IPPROTO_TCP); 207 npf_nc_cachetest(m, &npc, &nbuf); 208 ret = npf_ncode_process(&npc, nc_match6, &nbuf, NPF_LAYER_3); 209 fail |= retcode_fail_p("IPv6 mask", verbose, ret, 0); 210 m_freem(m); 211 212 return !fail; 213} 214