npfctl_build_code: generate TCP/UDP check for ports case when other blocks

do not imply L4 check; add an assert in npfctl_bpf_proto() and elsewhere.
This commit is contained in:
rmind 2014-05-31 22:41:37 +00:00
parent 7429e1daf1
commit 410bae3ffd
3 changed files with 29 additions and 13 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_bpf_comp.c,v 1.5 2014/05/15 02:34:29 rmind Exp $ */
/* $NetBSD: npf_bpf_comp.c,v 1.6 2014/05/31 22:41:37 rmind Exp $ */
/*-
* Copyright (c) 2010-2014 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npf_bpf_comp.c,v 1.5 2014/05/15 02:34:29 rmind Exp $");
__RCSID("$NetBSD: npf_bpf_comp.c,v 1.6 2014/05/31 22:41:37 rmind Exp $");
#include <stdlib.h>
#include <stdbool.h>
@ -62,7 +62,8 @@ __RCSID("$NetBSD: npf_bpf_comp.c,v 1.5 2014/05/15 02:34:29 rmind Exp $");
* something other than L4 header offset. Generally, when BPF_LDX is used.
*/
#define FETCHED_L3 0x01
#define X_EQ_L4OFF 0x02
#define CHECKED_L4 0x02
#define X_EQ_L4OFF 0x04
struct npf_bpf {
/*
@ -283,8 +284,8 @@ fetch_l3(npf_bpf_t *ctx, sa_family_t af, u_int flags)
}
/*
* Fetch L3 information. The coprocessor populates the following
* words in the scratch memory store:
* Call NPF_COP_L3 to fetch L3 information. The coprocessor
* populates the following words in the scratch memory store:
* - BPF_MW_IPVER: IP version (4 or 6).
* - BPF_MW_L4OFF: L4 header offset.
* - BPF_MW_L4PROTO: L4 protocol.
@ -369,6 +370,7 @@ npfctl_bpf_proto(npf_bpf_t *ctx, sa_family_t af, int proto)
uint32_t mwords[] = { BM_PROTO, 1, proto };
done_block(ctx, mwords, sizeof(mwords));
ctx->flags |= CHECKED_L4;
}
/*
@ -471,6 +473,7 @@ npfctl_bpf_ports(npf_bpf_t *ctx, u_int opts, in_port_t from, in_port_t to)
/* TCP and UDP port offsets are the same. */
assert(sport_off == offsetof(struct tcphdr, th_sport));
assert(dport_off == offsetof(struct tcphdr, th_dport));
assert(ctx->flags & CHECKED_L4);
assert(((opts & MATCH_SRC) != 0) ^ ((opts & MATCH_DST) != 0));
off = (opts & MATCH_SRC) ? sport_off : dport_off;
@ -516,11 +519,12 @@ void
npfctl_bpf_tcpfl(npf_bpf_t *ctx, uint8_t tf, uint8_t tf_mask, bool checktcp)
{
const u_int tcpfl_off = offsetof(struct tcphdr, th_flags);
const bool usingmask = tf_mask != tf;
/* X <- IP header length */
fetch_l3(ctx, AF_UNSPEC, X_EQ_L4OFF);
if (checktcp) {
const u_int jf = (tf_mask != tf) ? 3 : 2;
const u_int jf = usingmask ? 3 : 2;
assert(ctx->ingroup == false);
/* A <- L4 protocol; A == TCP? If not, jump out. */
@ -529,6 +533,8 @@ npfctl_bpf_tcpfl(npf_bpf_t *ctx, uint8_t tf, uint8_t tf_mask, bool checktcp)
BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, IPPROTO_TCP, 0, jf),
};
add_insns(ctx, insns_tcp, __arraycount(insns_tcp));
} else {
assert(ctx->flags & CHECKED_L4);
}
struct bpf_insn insns_tf[] = {
@ -537,7 +543,7 @@ npfctl_bpf_tcpfl(npf_bpf_t *ctx, uint8_t tf, uint8_t tf_mask, bool checktcp)
};
add_insns(ctx, insns_tf, __arraycount(insns_tf));
if (tf_mask != tf) {
if (usingmask) {
/* A <- (A & mask) */
struct bpf_insn insns_mask[] = {
BPF_STMT(BPF_ALU+BPF_AND+BPF_K, tf_mask),
@ -567,6 +573,7 @@ npfctl_bpf_icmp(npf_bpf_t *ctx, int type, int code)
const u_int type_off = offsetof(struct icmp, icmp_type);
const u_int code_off = offsetof(struct icmp, icmp_code);
assert(ctx->flags & CHECKED_L4);
assert(offsetof(struct icmp6_hdr, icmp6_type) == type_off);
assert(offsetof(struct icmp6_hdr, icmp6_code) == code_off);
assert(type != -1 || code != -1);

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_build.c,v 1.37 2014/05/15 02:34:29 rmind Exp $ */
/* $NetBSD: npf_build.c,v 1.38 2014/05/31 22:41:37 rmind Exp $ */
/*-
* Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npf_build.c,v 1.37 2014/05/15 02:34:29 rmind Exp $");
__RCSID("$NetBSD: npf_build.c,v 1.38 2014/05/31 22:41:37 rmind Exp $");
#include <sys/types.h>
#include <sys/mman.h>
@ -293,10 +293,10 @@ static bool
npfctl_build_code(nl_rule_t *rl, sa_family_t family, const opt_proto_t *op,
const filt_opts_t *fopts)
{
bool noproto, noaddrs, noports, need_tcpudp = false;
const addr_port_t *apfrom = &fopts->fo_from;
const addr_port_t *apto = &fopts->fo_to;
const int proto = op->op_proto;
bool noproto, noaddrs, noports;
npf_bpf_t *bc;
size_t len;
@ -317,7 +317,9 @@ npfctl_build_code(nl_rule_t *rl, sa_family_t family, const opt_proto_t *op,
switch (proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
break;
case -1:
need_tcpudp = true;
break;
default:
yyerror("invalid filter options for protocol %d", proto);
@ -344,6 +346,13 @@ npfctl_build_code(nl_rule_t *rl, sa_family_t family, const opt_proto_t *op,
npfctl_build_vars(bc, family, apto->ap_netaddr, MATCH_DST);
/* Build port-range blocks. */
if (need_tcpudp) {
/* TCP/UDP check for the ports. */
npfctl_bpf_group(bc);
npfctl_bpf_proto(bc, AF_UNSPEC, IPPROTO_TCP);
npfctl_bpf_proto(bc, AF_UNSPEC, IPPROTO_UDP);
npfctl_bpf_endgroup(bc);
}
npfctl_build_vars(bc, family, apfrom->ap_portrange, MATCH_SRC);
npfctl_build_vars(bc, family, apto->ap_portrange, MATCH_DST);

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_show.c,v 1.13 2014/03/14 11:29:45 rmind Exp $ */
/* $NetBSD: npf_show.c,v 1.14 2014/05/31 22:41:37 rmind Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npf_show.c,v 1.13 2014/03/14 11:29:45 rmind Exp $");
__RCSID("$NetBSD: npf_show.c,v 1.14 2014/05/31 22:41:37 rmind Exp $");
#include <sys/socket.h>
#include <netinet/in.h>
@ -248,7 +248,7 @@ static const struct mark_keyword_mapent {
u_int fwords;
} mark_keyword_map[] = {
{ BM_IPVER, "family %s", NULL, print_family, 1 },
{ BM_PROTO, "proto %s", NULL, print_proto, 1 },
{ BM_PROTO, "proto %s", ", ", print_proto, 1 },
{ BM_TCPFL, "flags %s", NULL, print_tcpflags, 2 },
{ BM_ICMP_TYPE, "icmp-type %s", NULL, print_number, 1 },
{ BM_ICMP_CODE, "code %s", NULL, print_number, 1 },