static char * parse_nbuf_chain(struct mbuf *m) { ifnet_t *dummy_ifp = npf_test_addif(IFNAME_TEST, false, false); char *s = kmem_zalloc(MBUF_CHAIN_LEN + 1, KM_SLEEP); nbuf_t nbuf; void *nptr; int n; nbuf_init(npf_getkernctx(), &nbuf, m, dummy_ifp); nptr = nbuf_advance(&nbuf, (random() % 16) + 1, (random() % 16) + 1); mbuf_consistency_check(&nbuf); assert(nptr != NULL); nbuf_reset(&nbuf); for (n = 0; ; ) { char d[4 + 1]; nptr = nbuf_ensure_contig(&nbuf, sizeof(uint32_t)); if (nptr == NULL) { break; } mbuf_consistency_check(&nbuf); memcpy(&d, nptr, sizeof(uint32_t)); d[sizeof(d) - 1] = '\0'; strcat(s, d); if (n + sizeof(uint32_t) == MBUF_CHAIN_LEN) { assert(nbuf_advance(&nbuf, sizeof(uint32_t) - 1, 0)); assert(!nbuf_advance(&nbuf, 1, 0)); break; } if (!nbuf_advance(&nbuf, sizeof(uint32_t), 0)) { break; } n += sizeof(uint32_t); } mbuf_consistency_check(&nbuf); return s; }
static int test_bpf_code(void *code, size_t size) { ifnet_t *dummy_ifp = npf_test_addif(IFNAME_TEST, false, false); npf_cache_t npc = { .npc_info = 0 }; bpf_args_t bc_args; struct mbuf *m; nbuf_t nbuf; int ret, jret; void *jcode; /* Layer 3 (IP + TCP). */ m = fill_packet(IPPROTO_TCP); nbuf_init(&nbuf, m, dummy_ifp); npf_cache_all(&npc, &nbuf); memset(&bc_args, 0, sizeof(bpf_args_t)); bc_args.pkt = m; bc_args.wirelen = m_length(m); bc_args.arg = &npc; ret = npf_bpf_filter(&bc_args, code, NULL); /* JIT-compiled code. */ jcode = npf_bpf_compile(code, size); if (jcode) { jret = npf_bpf_filter(&bc_args, NULL, jcode); assert(ret == jret); bpf_jit_freecode(jcode); } else if (lverbose) { printf("JIT-compilation failed\n"); } m_freem(m); return ret; } static uint32_t npf_bpfcop_run(u_int reg) { struct bpf_insn insns_npf_bpfcop[] = { BPF_STMT(BPF_MISC+BPF_COP, NPF_COP_L3), BPF_STMT(BPF_LD+BPF_W+BPF_MEM, reg), BPF_STMT(BPF_RET+BPF_A, 0), }; return test_bpf_code(&insns_npf_bpfcop, sizeof(insns_npf_bpfcop)); } static bool npf_bpfcop_test(void) { bool fail = false; /* A <- IP version (4 or 6) */ struct bpf_insn insns_ipver[] = { BPF_STMT(BPF_MISC+BPF_COP, NPF_COP_L3), BPF_STMT(BPF_RET+BPF_A, 0), }; fail |= (test_bpf_code(&insns_ipver, sizeof(insns_ipver)) != IPVERSION); /* BPF_MW_IPVERI <- IP version */ fail |= (npf_bpfcop_run(BPF_MW_IPVER) != IPVERSION); /* BPF_MW_L4OFF <- L4 header offset */ fail |= (npf_bpfcop_run(BPF_MW_L4OFF) != sizeof(struct ip)); /* BPF_MW_L4PROTO <- L4 protocol */ fail |= (npf_bpfcop_run(BPF_MW_L4PROTO) != IPPROTO_TCP); return fail; }