# $NetBSD: TODO.npf,v 1.15 2025/04/17 19:54:24 gdt Exp $

# Meta

This file intends to be the location for all work needing to be done
for npf within NetBSD, except for bugs that are straightforward enough
to live in gnats.  The presence of an item does not imply that there
is consensus that the item should be implemented.

(The older TODO list, last modified in May, 2020:
  https://www.netbsd.org/~rmind/npf/__tasklist.html
has been merged into this file.)

## Review all items to see if they are still relevant and correct.

# Syncing

## from https://github.com/rmind/npf/

Periodically, check this repo to see if there are changes/improvements
that are not in NetBDS and which are appopriate, and merge them.

## to https://github.com/rmind/npf/

Periodically, compare code between NetBSD and this repo, and file PRs
for changes in NetBSD as appropriate, when there are not already PRs.

## Merge https://github.com/rmind/npf doc subdir

rmind's repo has a doc directory.  Some content is in man pages and
thus available within NetBSD.  Understand if there are things that
aren't (likely), decide how to have them in NetBSD
(/usr/share/doc/npf?) and add them.

# Documentation

## Conversion Guides

Add instructions for converting configuration for other packet filters
to npf configuration.

## More Examples

## Man page nits

### npf.conf: rule group processing

Explain if groups are processed in the same order as npf.conf.
Explain what happens if a packet matches the group header, but does
not match a rule in the group.  Currently it is unclear exactly when
the default group is run, and if multiple matching groups might run.

### npf.conf dynamic ruleset

Dynamic rulesets are mentioned in npfctl, and blocklistd examples, but
they are not explained in npf.conf.  In addition to the basics, while
it is not expected that these rules be treated as if they have the
final flag, the code seems to do that.

# NetBSD integration

## save/restore

/etc/rc.d/npf lacks the ability to save and load state (stateful rules
and NAT).

# npfctl

## npfctl start does not load

npfctl start does not load the configuration if not loaded.
It is not clear you need to reload first. Or if it loads it should
print the error messages. Or it should be called enable/disable since
this is what it does. It does not "start" because like an engine with
no fuel, an npf with no configuration does not do much.

Alternatively: warn if there are no rules, or decide that npfctl
behaves as documented.

## better error reporting

although the framework checks the file for consistency, returning
EINVAL for system failures is probably not good enough. For example if
a module failed to autoload, it is probably an error and it should be
reported differently?

## handle array variables in more places

(Decide if this is just about npfctl or also about the kernel, and if
the latter move it.)

## support variables and inline sets which contain both IPv4 and IPv6 addresses

for example: $ext_if = { inet4(wm0), inet6(wm0) }

(Decide if this is just about npfctl or also about the kernel, and if
the latter move it.)

## support inline blocks with different types of data in the rule.

This will require a clean-up of the type system in
npfctl parser, since it is currently a bit of a mess. Examples:

	pass in from all to { inet4(wm0), $some_var, 10.0.0.1,  }
	pass in final proto tcp to 172.28.1.2 port { 161, 162 }
	pass in final proto { tcp, udp } to 172.28.1.2 port 53

[MOSTLY DONE?]

(Decide if this is just about npfctl or also about the kernel, and if
the latter move it.)

## npf show improvements

Consistent `npfctl show' output with rule syntax.  Difficult/messy
because rules are compiled into the byte-code.

Add examples of what is wrong.

## -D option to set variables

Allow `npfctl -D varname=value` to set a variable, as if were defined
in the config file.  See pfctl(8).

# Architectural changes

## Layer 2 filtering

1. All rules in NPF are added to a ruleset.  At this moment, it is assumed
   that there is only one ruleset and all rules are processed at layer 3.
   One approach is to support another ruleset for layer 2 (or rather, have
   capability to specify the "starting layer").

2. One way to separate L2 and L3 rules could be by marking groups.  In NPF,
   a group is just a rule (i.e. rules can be nested).

3. npfctl: update the parser such that the group would have an option for
   specifying a layer.  See "group_opts" token in npf_parse.y file.  Also,
   we may want to add support for "hwaddr <mac>" syntax or something.

4. npfctl_build_rule() code will need to distinguish groups/rules which
   were marked as layer 2, i.e. byte-code generation (npfctl_build_code()
   and the logic in it) needs to know that we are starting from Ethernet
   header and not IP header.  Note: it needs to be passed to all nested
   rules, so basically take the option from the "current group".

5. For a start (i.e. less work to do), you can just add byte-code to parse
   Ethernet header and compare the MAC addresses.  Just return "not supported"
   error for any other filter pattern.

6. libnpf: create a new ruleset for L2 and add all groups (and its nested
   rules) there.  To keep it simpler, we can add npf_rule_setlayer() function
   and just handle this separation in libnpf rather than npfctl.

7. libnpf-kernel: currently, proplib dictionary has only one "ruleset" dict.
   This needs to be split into "ruleset-l3" and "ruleset-l2".  Retrieve and
   construct a new ruleset in npfctl_reload(); it is simple, but disgusting
   proplib code.  It is just re-using the existing code to handle another
   ruleset.

8. Kernel: add a new handler in npf_handler.c, e.g. npf_packet_l2handler()
   or something.  Register it in npf_pfil_register() using Ethernet pfil
   hook.  In the handler, call npf_ruleset_inspect() passing L2 ruleset.

## Consider single large BPF program

Implement NPF rules as a single large BPF program, instead of
providing BPF byte-code per each rule. In combination with BPF JIT
compilation, such approach would significantly improve the performance
of very large rulesets. Problems: BPF byte-code limitations; we can
either extend the byte-code or workaround them.

## Multiple rule matching

Multiple rule matching to call the rule-procedures or a suitable
design alternative to that.

(Explain what this means more clearly.)

## ipchains-like feature

Implement ipchains-like feature to support nested rules and sharing of
a rule group. NPF already supports nested rules. Unresolved questions
are: 1) what kind of complexity of rule chains do we want to support,
e.g. a directed graph with loop resolution or more strict hierarchy
which does not allow jumping up the chain? 2) syntax in npf.conf file.

## Support for packets arriving at or departing the socket layer

Similar to how one can do this in nftables, add a way to write a rule
that will be applied to all packets being delivered to sockets, or
really processed by the system as a host rather than simply forwarded.
The point is to be able to express rules like "block connections to
this machine's ssh daemon, but don't block ssh connections that are
merely being routed", without having to match on addresses.

## redundancy and load balancing

Redundancy and load balancing: initially, add state replication and
replace in-kernel CARP/VRRP with a userlevel daemon.

Check "Note: we probably want to eliminate proplib in NPF before doing
this." and drop if proplib has in fact been eliminated.

## QoS

QoS: rate limiting, traffic shaping, prioritising. Question: how much
of this should be a part of the packet filter and how much of the
network stack (merely involving some integration with the packet
filters)?

## address/port and port in tables

Tables currently contain addresses. Add support for address/port
tuples, and ports.

## Separate mss clamping from normal rules

Currently, mss clamping is a rule procedure and has to be specified on
a matching rule.  But, if there are both firewall rules and a desire
to clamp, then one has to add clamping to all rules.  This item is
about having a way to express rules normally, and also say that
clamping shouldhappen.

	http://mail-index.netbsd.org/tech-net/2017/01/15/msg006224.html

# Features (not needing architectural changes)

## Add an extension for "route-to"

The essence is to change the next hop of a packet if it matches a
rule.

	http://mail-index.netbsd.org/tech-net/2014/05/19/msg004526.html 

## support for ALTQ

ALTQ is a QoS scheme, and it expects a way to classify packets so that
different flows can be treated differently.  Currently, ALTQ in NetBSD
uses pf.  (An earlier comment indicated a solution might involve mbuf
tags.)

## Support for NAT64 i.e. the protocol translation. 

## MiniUPnP

Add support for MiniUPnP (see http://miniupnp.free.fr/ web page). 

## add support for "with short"

(Clarify: is this about dropping packets that are shorter than they
should be?  Why would the user choose?)

## Add specific kinds of ICMP unreachable

Currently, rules are documented to allow returning `ICMP UNREACHABLE`
given the keyword `return-icmp`.  Probably this is ICMP Admin
Prohibited, but this is not clear.

This item is about different or additional keywords to allow the user
to specify network, host, or port unreachable instead.

# Security

## Extra measures to protect npf from SYN flood attacks.

E.g. accelerate connection expiration on low memory or after certain
threshold. The timeout can also be self-balancing.  This item is about
protecting npf state in situations where excessive SYNs arrive in
situations where a legitimate SYN should trigger a state entry.

## Consider blind reset attacks (see RFC 5961).

This is about the situation when npf is doing stateful processing on a
TCP connection and only allowing packets matching the connection.
Extend the definition of a packet matching the connection to meet the
new rules in RFC5961, and perhaps generate the specified response
packets.

## Add counters

Add a hit counter to rules, or some other way so that the user can say
"show me the list of rules and for each rules, how many times it was
invoked".   This is similar to ipfilter's `ipfstat -inh`.

# General

## IPv4 options

Implement "block return-icmp in log final all with ipopts".
(Explain if this is more than "enable writing rules to match packets
with ip options".)

Consider defaulting to blocking options, with "allow-ip4opts" to
enable them.

## IPv6 options

(Jointly with IPv4 options.)

Perhaps a limited set (IPPROTO_ROUTING, IPPROTO_HOPOPTS and
IPPROTO_DSTOPTS) by default, and "allow-ip6opts" to enable others.

## add an ioctl, similar to PF's DIOCNATLOOK and IPF's SIOCGNATL

document it so that it can be added in third-party software, like:
   https://github.com/squid-cache/squid/blob/5b74111aff8948e869959113241adada0cd488c2/src/ip/Intercept.cc#L263

### patch squid to support transparent-proxy with NPF.

(Likely, simply using the ioctl from the previous item.)

## support IPv6 jumbograms

(Explain what is or is not supported now, and what needs to happen
differently.)

## IPv6 reassembly

Investigate and fix the IPv6 reassembly (there is a memory leak).

## nbuf_ensure_writable

Use nbuf_ensure_writable() where appropriate.

# Low priority items

These items are left in the list, but there's no reason to think
anyone will address them any time soon, or that they are high enough
priority that anyone should.  They can of course be moved (up likely
clarified if someeone, especially someone intending to work on them,
doesn't see it that way.  (Perhaps we should drop them, but for now
they are parked.)

## NAT Application Level Gateways for FTP

Generally, FTP is done in passive mode, so that the data connection is
created by the client, and no particular support is needed in
firewalls.  This item is about creating an alg that allows the
(regular, not passive mode) inbound connection from the server, based
on watching the control connection.

(It is likely that there are almost no remaining uses of active FTP,
and thus it is unlikely this would be implemented.)

## Consider experimentation to use bloom filters against certain DoS attacks.

(This needs much more clarity.)

## support large IPv6 options

as explained here:
       http://mail-index.netbsd.org/tech-net/2018/04/08/msg006786.html
But it's not a big problem - perhaps we don't care at all.

## TCP FSM enhancement

Minor TCP FSM investigation: should it be not allowed to immediately
re-open the connection after RST or FIN?

(Explain what this means, how it relates to standards, and what the
concerns are.)