Skip to content

PR: NPF Layer 2 filtering#50

Closed
Emmankoko wants to merge 14 commits intoNetBSD:trunkfrom
Emmankoko:npflayer2
Closed

PR: NPF Layer 2 filtering#50
Emmankoko wants to merge 14 commits intoNetBSD:trunkfrom
Emmankoko:npflayer2

Conversation

@Emmankoko
Copy link
Copy Markdown

This is work covering the development of media access control filtering in NPF

has been tested on my netbsd using ssh connections and checking the statistics and everything works as expected.
work available and opened for review.

test to be written after completed review.

Emmankoko added 7 commits May 18, 2025 14:33
we ensure that layer 2 rules are inserted in layer 2 groups

and layer 3 rules in layer 3 groups
here, rules are moved up to kernel and only l2 flagged bytcode are executed by layer2 handler
and l3 flagged byte code are executed by l3 handler

for l2, we use per interface filter hooks, we traverse all the interfaces on the system and hook our function with the ifnet pointer as
key in the hook head

we see a lot of duplications here: the decision to leave code in the different layer duplicated
reduces a lot of branching and also personal decision to keep them as decoupled as possible.
and also add ether pass and ether block stats in npfctl stat
Comment thread sys/net/npf/npf_handler.c Outdated
* including the interface the frame is traveling on
*/
nbuf_init(npf, &nbuf, *mp, ifp);
memset(&npc, 0, sizeof(npf_cache_t));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sizeof(npc)

Comment thread sys/net/npf/npf_os.c Outdated

if (npf_ph_ether) {
error = pfil_add_hook(npfos_layer2_handler, npf,
PFIL_ALL, npf_ph_ether);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong indent

Comment thread sys/net/npf/npf_os.c Outdated
register_etherpfil_hook(npf_t *npf, ifnet_t *ifp, int i)
{
int error = 0;
static pfil_head_t * npf_ph_ether;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong whitespace

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still wrong whitespace

Comment thread sys/net/npf/npf_os.c Outdated
destroy_pfilether_hook(npf_t *npf)
{
int i = 0;
while(npf_ph_etherlist[i]) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

space after keyword

Comment thread sys/net/npf/npf_os.c Outdated
{
int i = 0;
while(npf_ph_etherlist[i]) {
pfil_head_t *npf_ph_ether;
Copy link
Copy Markdown
Contributor

@zoulasc zoulasc Jun 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not assign in the decl?

Comment thread usr.sbin/npf/npfctl/npf_bpf_comp.c Outdated
}

} else if (type && type != ctx->eth_type) {
errx(EXIT_FAILURE, "ether type mismatch");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

print the types that did not match

Comment thread usr.sbin/npf/npfctl/npf_bpf_comp.c
Comment thread usr.sbin/npf/npfctl/npf_bpf_comp.c Outdated
const uint32_t *awords = (const uint32_t *)ether_addr;

off = (opts & MATCH_SRC) ? offsetof(struct ether_header, ether_shost) :
offsetof(struct ether_header, ether_dhost);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad indent

Comment thread usr.sbin/npf/npfctl/npf_bpf_comp.c Outdated
{
unsigned off;
assert(((opts & MATCH_SRC) != 0) ^ ((opts & MATCH_DST) != 0));
const uint32_t *awords = (const uint32_t *)ether_addr;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you know that this is aligned properly?

Comment thread usr.sbin/npf/npfctl/npf_build.c Outdated
bc = npfctl_bpf_create();
if (fopts->layer == NPF_RULE_LAYER_3) {
if (!build_l3_code(bc, rl, family, popts, fopts))
return false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad indent

Comment thread usr.sbin/npf/npfctl/npf_build.c Outdated
static uint32_t
npf_rule_layer_compat(nl_rule_t *cg, uint32_t layer)
{
const char *str = (layer & NPF_RULE_LAYER_2) ? "layer 2" : "layer 3";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are using 2 flags one for layer 2 and one for layer 3, then you test layer 2 here and in the code above you test layer 3 (with the else being the other one). Why do you need two flags? Are we planning to filter more layers in the future? And if we do, then if-then-else is not good enough.

Comment thread usr.sbin/npf/npfctl/npf_build.c Outdated

if ((attr & layer) == 0) {
yyerror("cannot insert %s rules in this group"
" make sure to insert same layer rules in same group ", str);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad indent

Comment thread usr.sbin/npf/npfctl/npf_build.c Outdated
memset(&imfopts, 0, sizeof(filt_opts_t));
memcpy(&imfopts.fo_from, ap1, sizeof(addr_port_t));
imfopts.layer = NPF_RULE_LAYER_3;
memcpy(&imfopts.filt.opt3.fo_from, ap1, sizeof(addr_port_t));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sizeof (infmopts....)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still applies

Comment thread usr.sbin/npf/npfctl/npf_data.c Outdated

while (*cp) {
if (!isxdigit(*cp))
yyerror("%s", err);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Print the address that is bad too.

Comment thread usr.sbin/npf/npfctl/npf_data.c Outdated
if (*cp == '\0')
return;
else
yyerror("%s", err);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be more specific in the error.

Comment thread usr.sbin/npf/npfctl/npf_data.c Outdated
}

switch (*cp) {
case ':':
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong indent.

Comment thread usr.sbin/npf/npfctl/npf_show.c Outdated

_DIAGASSERT(type != NULL);

easprintf(&a, "%c%c%02x%02x", 'E', 'x', type[0], type[1]);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why %c%c instead of Ex

Comment thread usr.sbin/npf/npfctl/npf_show.c
Comment thread usr.sbin/npf/npftest/libnpftest/npf_l2rule_test.c
Comment thread usr.sbin/npf/npftest/libnpftest/npf_rule_test.c
Comment thread usr.sbin/npf/npfctl/npf_bpf_comp.c
Comment thread usr.sbin/npf/npfctl/npf_bpf_comp.c Outdated
void
fetch_ether_type(npf_bpf_t *ctx, uint16_t type)
{
if ((ctx->flags & FETCHED_L2) == 0 || (type && ctx->eth_type == 0)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

early returns, reverse the if logic and return early so you can unindent the code.

Comment thread usr.sbin/npf/npfctl/npf_build.c
Comment thread usr.sbin/npf/npfctl/npf_build.c Outdated
static nl_rule_t *
set_defgroup(nl_rule_t *rl, nl_rule_t *def_group, int attr)
{
const char *str = (attr & NPF_RULE_LAYER_3) ? "layer 3" : "layer 2";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used by the other error so why always compute it?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also you have code figuring out the layer string again below, centralize it to a method.

Comment thread usr.sbin/npf/npfctl/npf_build.c Outdated
if ((attr & layer) == 0) {
/* only set the layer strings when you need them */
const char *str;
if (layer & NPF_RULE_LAYER_2)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is the other code.

Comment thread usr.sbin/npf/npfctl/npf_build.c Outdated
memset(&imfopts, 0, sizeof(filt_opts_t));
memcpy(&imfopts.fo_from, ap1, sizeof(addr_port_t));
imfopts.layer = NPF_RULE_LAYER_3;
memcpy(&imfopts.filt.opt3.fo_from, ap1, sizeof(addr_port_t));
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still applies

Comment thread usr.sbin/npf/npfctl/npf_data.c Outdated

filt_opts_t
npfctl_parse_l3filt_opt(npfvar_t *src_addr, npfvar_t *src_port, bool tnot,
npfvar_t *dst_addr, npfvar_t *dst_port, bool fnot)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad indent

Comment thread usr.sbin/npf/npfctl/npf_data.c Outdated

filt_opts_t
npfctl_parse_l2filt_opt(npfvar_t *src_addr, bool fnot, npfvar_t *dst_addr,
bool tnot, uint16_t eth_type)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bad indent

Comment thread usr.sbin/npf/npfctl/npfctl.h Outdated
enum { /* book marks for L2 */
BM_ETHER_TYPE, BM_SRC_ETHER, BM_DST_ETHER, BM_SRC_ENEG, BM_DST_ENEG,

//BML2_COUNT // total number of l2 marks
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this?

Comment thread usr.sbin/npf/npfctl/npf_bpf_comp.c Outdated

off = (opts & MATCH_SRC) ? offsetof(struct ether_header, ether_shost) :
offsetof(struct ether_header, ether_dhost);
const uint32_t word_offset = sizeof(uint32_t);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forget about word_offset and use sizeof(mac_word) like we do in the memcpy case.

Comment thread usr.sbin/npf/npfctl/npf_build.c Outdated
static nl_rule_t * the_rule = NULL;
static bool npf_conf_built = false;

static bool l2_group = false;;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this global, and why ;;?

Comment thread usr.sbin/npf/npfctl/npf_build.c Outdated
static bool npf_conf_built = false;

static bool l2_group = false;;
static nl_rule_t * defgroup = NULL;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to defgroup_l3 for clarity?

@Emmankoko Emmankoko closed this Jul 1, 2025
netbsd-srcmastr pushed a commit that referenced this pull request Oct 11, 2025
	sys/dev/usb/xhci.c: revision 1.192

Don't generate duplicate events when sending ZLP.

Patch from sc_dying as posted to tech-kern.
Addresses PR/59678.
netbsd-srcmastr pushed a commit that referenced this pull request Oct 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants