Index: usr.sbin/npf/npfctl/npf_bpf_comp.c =================================================================== RCS file: /cvsroot/src/usr.sbin/npf/npfctl/npf_bpf_comp.c,v retrieving revision 1.16 diff -p -u -r1.16 npf_bpf_comp.c --- usr.sbin/npf/npfctl/npf_bpf_comp.c 30 May 2020 14:16:56 -0000 1.16 +++ usr.sbin/npf/npfctl/npf_bpf_comp.c 26 Apr 2024 18:01:32 -0000 @@ -206,12 +206,22 @@ fixup_jumps(npf_bpf_t *ctx, u_int start, * Fixup the "magic" value. Swap only the "magic" jumps. */ - if (insn->jt == JUMP_MAGIC) { - insn->jt = fail_off; + if (insn->jf == JUMP_MAGIC) { + if (swap && insn->jt) { + insn->jf = 0; + } else { + insn->jf = fail_off; + insn->jt = 0; + } seen_magic = true; } - if (insn->jf == JUMP_MAGIC) { - insn->jf = fail_off; + if (insn->jt == JUMP_MAGIC) { + if (swap && insn->jf) { + insn->jt = 0; + } else { + insn->jt = fail_off; + insn->jf = 0; + } seen_magic = true; } @@ -496,13 +506,14 @@ npfctl_bpf_proto(npf_bpf_t *ctx, unsigne * npfctl_bpf_cidr: code block to match IPv4 or IPv6 CIDR. * * => IP address shall be in the network byte order. + * */ void npfctl_bpf_cidr(npf_bpf_t *ctx, unsigned opts, sa_family_t af, const npf_addr_t *addr, const npf_netmask_t mask) { const uint32_t *awords = (const uint32_t *)addr; - unsigned nwords, length, maxmask, off; + unsigned nwords, length, maxmask, off, fail_off; assert(((opts & MATCH_SRC) != 0) ^ ((opts & MATCH_DST) != 0)); assert((mask && mask <= NPF_MAX_NETMASK) || mask == NPF_NO_NETMASK); @@ -513,14 +524,12 @@ npfctl_bpf_cidr(npf_bpf_t *ctx, unsigned off = (opts & MATCH_SRC) ? offsetof(struct ip, ip_src) : offsetof(struct ip, ip_dst); - nwords = sizeof(struct in_addr) / sizeof(uint32_t); break; case AF_INET6: maxmask = 128; off = (opts & MATCH_SRC) ? offsetof(struct ip6_hdr, ip6_src) : offsetof(struct ip6_hdr, ip6_dst); - nwords = sizeof(struct in6_addr) / sizeof(uint32_t); break; default: abort(); @@ -531,6 +540,14 @@ npfctl_bpf_cidr(npf_bpf_t *ctx, unsigned length = (mask == NPF_NO_NETMASK) ? maxmask : mask; + /* Compute number of words to check */ + nwords = howmany(length, 32); + /* Compute offset to failure path */ + fail_off = length / 32 * 2 + (length % 32 ? 3 : 0) - 1; + + if (nwords * 32 > maxmask) + abort(); + /* CAUTION: BPF operates in host byte-order. */ for (unsigned i = 0; i < nwords; i++) { const unsigned woff = i * sizeof(uint32_t); @@ -545,8 +562,8 @@ npfctl_bpf_cidr(npf_bpf_t *ctx, unsigned wordmask = 0xffffffff << (32 - length); length = 0; } else { - /* The mask became zero - skip the rest. */ - break; + /* The mask became zero - this cannot happen */ + abort(); } /* A <- IP address (or one word of it) */ @@ -554,6 +571,7 @@ npfctl_bpf_cidr(npf_bpf_t *ctx, unsigned BPF_STMT(BPF_LD+BPF_W+BPF_ABS, off + woff), }; add_insns(ctx, insns_ip, __arraycount(insns_ip)); + fail_off--; /* A <- (A & MASK) */ if (wordmask) { @@ -561,13 +579,17 @@ npfctl_bpf_cidr(npf_bpf_t *ctx, unsigned BPF_STMT(BPF_ALU+BPF_AND+BPF_K, wordmask), }; add_insns(ctx, insns_mask, __arraycount(insns_mask)); + fail_off--; } /* A == expected-IP-word ? */ struct bpf_insn insns_cmp[] = { BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, word, 0, JUMP_MAGIC), }; + if (i < nwords-1) + insns_cmp[0].jt = fail_off; add_insns(ctx, insns_cmp, __arraycount(insns_cmp)); + fail_off--; } uint32_t mwords[] = { Index: usr.sbin/npf/npftest/npftest.c =================================================================== RCS file: /cvsroot/src/usr.sbin/npf/npftest/npftest.c,v retrieving revision 1.27 diff -p -u -r1.27 npftest.c --- usr.sbin/npf/npftest/npftest.c 8 Aug 2023 10:35:48 -0000 1.27 +++ usr.sbin/npf/npftest/npftest.c 26 Apr 2024 18:01:32 -0000 @@ -39,20 +39,21 @@ __dead static void usage(const char *progname) { printf("usage:\n" - " %s [ -q | -v ] [ -c ] " - "[ -i ] < -b | -t | -s file >\n" - " %s -T -c \n" + " %s [ -q | -v ] [ -i -s ] -b -c -p \n" + " %s [ -q | -v ] [ -i -s ] -t\n" + " %s [ -q | -v ] [ -i -s ] -T \n" " %s -L\n" "where:\n" - "\t-b: benchmark\n" - "\t-t: regression test\n" + "\t-b benchmark\n" + "\t-t regression test\n" "\t-T : specific test\n" "\t-s : pcap stream\n" "\t-c : NPF configuration file\n" "\t-i : primary interface\n" - "\t-L: list testnames and description for -T\n" - "\t-q: quiet mode\n" - "\t-v: verbose mode\n", + "\t-L list testnames and description for -T\n" + "\t-q quiet mode\n" + "\t-v verbose mode\n", + "\t-p set RUMP_NCPU\n", progname, progname, progname); exit(EXIT_FAILURE); } Index: usr.sbin/npf/npftest/npftest.conf =================================================================== RCS file: /cvsroot/src/usr.sbin/npf/npftest/npftest.conf,v retrieving revision 1.9 diff -p -u -r1.9 npftest.conf --- usr.sbin/npf/npftest/npftest.conf 30 May 2020 14:16:56 -0000 1.9 +++ usr.sbin/npf/npftest/npftest.conf 26 Apr 2024 18:01:32 -0000 @@ -56,6 +56,7 @@ group "ext" on $ext_if { group "int" on $int_if { ruleset "test-rules" + block in final from $local_ip3 pass stateful out final to $local_ip2 pass out final to $local_ip3 block final to $local_ip4 Index: usr.sbin/npf/npftest/libnpftest/npf_rule_test.c =================================================================== RCS file: /cvsroot/src/usr.sbin/npf/npftest/libnpftest/npf_rule_test.c,v retrieving revision 1.19 diff -p -u -r1.19 npf_rule_test.c --- usr.sbin/npf/npftest/libnpftest/npf_rule_test.c 25 Aug 2019 13:21:03 -0000 1.19 +++ usr.sbin/npf/npftest/libnpftest/npf_rule_test.c 26 Apr 2024 18:01:32 -0000 @@ -52,6 +52,10 @@ static const struct test_case { .ifname = IFNAME_INT, .di = PFIL_OUT, .stateful_ret = RESULT_BLOCK, .ret = RESULT_BLOCK }, + { .src = "10.1.1.3", .dst = "10.1.1.1", + .ifname = IFNAME_INT, .di = PFIL_IN, + .stateful_ret = RESULT_BLOCK, .ret = RESULT_BLOCK + }, };