kernel - Fix pf-based NAT
authorMatthew Dillon <dillon@apollo.backplane.com>
Sun, 29 Jun 2014 06:46:43 +0000 (23:46 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Sun, 29 Jun 2014 06:46:43 +0000 (23:46 -0700)
commit32772c966878dab0489c85e891a13e58d28933db
tree81001ecd3c1c589e56b54f9740dc883574c30df2
parente398f1335dbd1927acc8bdd9ceee047678521545
kernel - Fix pf-based NAT

* NAT may not always be able to select a translated addr/port that is
  compatible with the source addr/port.  In this situation return packets
  from the translated target won't be able to find the state structure.

  This occurs if static-port is used or if the port range is insufficent
  for PF to be able to find a hash-compatible addr/port.

  This also occurs for UDP because the toeplitz hash does not appear to
  include a port (so there's nothing PF NAT can do to make it
  hash-compatible).

* In situations where PF believes a translation is not hash-compatible,
  the pf_state_key will be placed on a global RBTREE instead of the
  cpu-localized RBTREE.  This tree is checked and modified with a separate
  lock (shared when doing lookups, exclusive when doing adjustments).

  The nominal pf_find_state*() code will now check the global RBTREE if the
  state cannot be found in the localized tree.

* Modifications to the pf_state structure are now exclusively locked to
  handle the case where a state structure might be used by multiple cpu's
  at the same time.  This can only occur for translations such as NAT.

* The TCP code is not allowed to destroy state on connection reuse unless
  the state is cpu-local.  If it is not cpu-local the TCP code will mark
  the state for an immediate purge (within the next second).

* Add a TSO flag check to pf_route(), which is called via NAT.  Locally
  originated packets may have been built with TSO.  For PF NAT, we can
  only assume that the target interface will be compatible and allow the
  packet through (not try to fragment it, which won't work well anyway for
  TCP packets).
sys/net/pf/if_pfsync.c
sys/net/pf/if_pfsync.h
sys/net/pf/pf.c
sys/net/pf/pf_ioctl.c
sys/net/pf/pfvar.h