Module Name: src
Committed By: rmind
Date: Fri Dec 6 01:33:37 UTC 2013
Modified Files:
src/sys/net/npf: npf.h npf_alg.c npf_alg_icmp.c npf_bpf.c npf_impl.h
npf_inet.c npf_nat.c npf_session.c
Log Message:
NPF:
- Adjust NAT to not assume flow direction in some cases and thus support
less usual setups which are possible when using 'map' with a custom
filter criteria.
- Introduce NPF_SRC/NPF_DST and replace npc_src/npc_dst with npc_ips[2]
for more convenient handling.
- ICMP ALG: restrict matching only to the outgoing traffic, but be more
direction-agnostic elsewhere.
To generate a diff of this commit:
cvs rdiff -u -r1.33 -r1.34 src/sys/net/npf/npf.h
cvs rdiff -u -r1.9 -r1.10 src/sys/net/npf/npf_alg.c
cvs rdiff -u -r1.17 -r1.18 src/sys/net/npf/npf_alg_icmp.c
cvs rdiff -u -r1.5 -r1.6 src/sys/net/npf/npf_bpf.c
cvs rdiff -u -r1.44 -r1.45 src/sys/net/npf/npf_impl.h
cvs rdiff -u -r1.27 -r1.28 src/sys/net/npf/npf_inet.c
cvs rdiff -u -r1.22 -r1.23 src/sys/net/npf/npf_nat.c
cvs rdiff -u -r1.29 -r1.30 src/sys/net/npf/npf_session.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/npf/npf.h
diff -u src/sys/net/npf/npf.h:1.33 src/sys/net/npf/npf.h:1.34
--- src/sys/net/npf/npf.h:1.33 Tue Nov 12 00:46:34 2013
+++ src/sys/net/npf/npf.h Fri Dec 6 01:33:37 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: npf.h,v 1.33 2013/11/12 00:46:34 rmind Exp $ */
+/* $NetBSD: npf.h,v 1.34 2013/12/06 01:33:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -104,18 +104,24 @@ typedef uint8_t npf_netmask_t;
typedef struct {
/* Information flags. */
uint32_t npc_info;
- /* Pointers to the IP v4/v6 addresses. */
- npf_addr_t * npc_srcip;
- npf_addr_t * npc_dstip;
- /* Size (v4 or v6) of IP addresses. */
+
+ /*
+ * Pointers to the IP source and destination addresses,
+ * and the address length (4 for IPv4 or 16 for IPv6).
+ */
+ npf_addr_t * npc_ips[2];
uint8_t npc_alen;
+
+ /* IP header length and L4 protocol. */
uint8_t npc_hlen;
uint16_t npc_proto;
+
/* IPv4, IPv6. */
union {
struct ip * v4;
struct ip6_hdr * v6;
} npc_ip;
+
/* TCP, UDP, ICMP. */
union {
struct tcphdr * tcp;
@@ -132,6 +138,9 @@ npf_iscached(const npf_cache_t *npc, con
return __predict_true((npc->npc_info & inf) != 0);
}
+#define NPF_SRC 0
+#define NPF_DST 1
+
/*
* Network buffer interface.
*/
Index: src/sys/net/npf/npf_alg.c
diff -u src/sys/net/npf/npf_alg.c:1.9 src/sys/net/npf/npf_alg.c:1.10
--- src/sys/net/npf/npf_alg.c:1.9 Sun Jun 2 02:20:04 2013
+++ src/sys/net/npf/npf_alg.c Fri Dec 6 01:33:37 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_alg.c,v 1.9 2013/06/02 02:20:04 rmind Exp $ */
+/* $NetBSD: npf_alg.c,v 1.10 2013/12/06 01:33:37 rmind Exp $ */
/*-
* Copyright (c) 2010-2013 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_alg.c,v 1.9 2013/06/02 02:20:04 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_alg.c,v 1.10 2013/12/06 01:33:37 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -58,8 +58,6 @@ struct npf_alg {
u_int na_slot;
};
-#define NPF_MAX_ALGS 8
-
/* List of ALGs and the count. */
static pserialize_t alg_psz __cacheline_aligned;
static npf_alg_t alg_list[NPF_MAX_ALGS] __read_mostly;
@@ -218,7 +216,7 @@ npf_alg_match(npf_cache_t *npc, nbuf_t *
* npf_alg_exec: execute ALG hooks for translation.
*/
void
-npf_alg_exec(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, int di)
+npf_alg_exec(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw)
{
int s;
@@ -227,7 +225,7 @@ npf_alg_exec(npf_cache_t *npc, nbuf_t *n
npf_alg_func_t func;
if ((func = alg_tfunc[i]) != NULL) {
- func(npc, nbuf, nt, di);
+ func(npc, nbuf, nt, (int)forw);
}
}
pserialize_read_exit(s);
Index: src/sys/net/npf/npf_alg_icmp.c
diff -u src/sys/net/npf/npf_alg_icmp.c:1.17 src/sys/net/npf/npf_alg_icmp.c:1.18
--- src/sys/net/npf/npf_alg_icmp.c:1.17 Sun Jun 2 02:20:04 2013
+++ src/sys/net/npf/npf_alg_icmp.c Fri Dec 6 01:33:37 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_alg_icmp.c,v 1.17 2013/06/02 02:20:04 rmind Exp $ */
+/* $NetBSD: npf_alg_icmp.c,v 1.18 2013/12/06 01:33:37 rmind Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.17 2013/06/02 02:20:04 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.18 2013/12/06 01:33:37 rmind Exp $");
#include <sys/param.h>
#include <sys/module.h>
@@ -106,8 +106,8 @@ npf_alg_icmp_modcmd(modcmd_t cmd, void *
}
/*
- * npfa_icmp_match: ALG matching inspector - determines ALG case and
- * associates ALG with NAT entry.
+ * npfa_icmp_match: match inspector - determines ALG case and associates
+ * our ALG with the NAT entry.
*/
static bool
npfa_icmp_match(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, int di)
@@ -119,8 +119,8 @@ npfa_icmp_match(npf_cache_t *npc, nbuf_t
KASSERT(npf_iscached(npc, NPC_IP46));
KASSERT(npf_iscached(npc, NPC_LAYER4));
- /* Check for low TTL. */
- if (ip->ip_ttl > TR_MAX_TTL) {
+ /* Check for low TTL. Also, we support outbound NAT only. */
+ if (ip->ip_ttl > TR_MAX_TTL || di != PFIL_OUT) {
return false;
}
@@ -303,7 +303,7 @@ npfa_icmp_session(npf_cache_t *npc, nbuf
bool ret, forw;
#define SWAP(type, x, y) { type tmp = x; x = y; y = tmp; }
- SWAP(npf_addr_t *, enpc.npc_srcip, enpc.npc_dstip);
+ SWAP(npf_addr_t *, enpc.npc_ips[NPF_SRC], enpc.npc_ips[NPF_DST]);
switch (enpc.npc_proto) {
case IPPROTO_TCP:
@@ -339,15 +339,15 @@ npfa_icmp_session(npf_cache_t *npc, nbuf
}
/*
- * npfa_icmp_nat: ALG inbound translation inspector, rewrite IP address
- * in the IP header, which is embedded in ICMP packet.
+ * npfa_icmp_nat: ALG translator - rewrites IP address in the IP header
+ * which is embedded in ICMP packet. Note: backwards stream only.
*/
static bool
-npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, int di)
+npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, int forw)
{
npf_cache_t enpc;
- if (di != PFIL_IN || !npf_iscached(npc, NPC_ICMP))
+ if (forw || !npf_iscached(npc, NPC_ICMP))
return false;
if (!npfa_icmp_inspect(npc, nbuf, &enpc))
return false;
@@ -365,6 +365,9 @@ npfa_icmp_nat(npf_cache_t *npc, nbuf_t *
* Retrieve the original address and port, then calculate ICMP
* checksum for these changes in the embedded packet. While data
* is not rewritten in the cache, save IP and TCP/UDP checksums.
+ *
+ * XXX: Assumes NPF_NATOUT (source address/port). Currently,
+ * npfa_icmp_match() matches only for the PFIL_OUT traffic.
*/
const int proto = enpc.npc_proto;
uint16_t ipcksum = 0, l4cksum = 0;
@@ -377,7 +380,7 @@ npfa_icmp_nat(npf_cache_t *npc, nbuf_t *
const struct ip *eip = enpc.npc_ip.v4;
ipcksum = eip->ip_sum;
}
- cksum = npf_addr_cksum(cksum, enpc.npc_alen, enpc.npc_srcip, addr);
+ cksum = npf_addr_cksum(cksum, enpc.npc_alen, enpc.npc_ips[NPF_SRC], addr);
switch (proto) {
case IPPROTO_TCP: {
@@ -401,10 +404,10 @@ npfa_icmp_nat(npf_cache_t *npc, nbuf_t *
/*
* Rewrite the source IP address and port of the embedded IP header,
- * which represents the original packet, therefore passing PFIL_OUT.
- * This updates the checksums in the embedded packet.
+ * which represents the original packet. This updates the checksums
+ * in the embedded packet.
*/
- if (npf_nat_translate(&enpc, nbuf, nt, false, PFIL_OUT)) {
+ if (npf_nat_translate(&enpc, nbuf, nt, forw)) {
return false;
}
Index: src/sys/net/npf/npf_bpf.c
diff -u src/sys/net/npf/npf_bpf.c:1.5 src/sys/net/npf/npf_bpf.c:1.6
--- src/sys/net/npf/npf_bpf.c:1.5 Sat Nov 23 19:32:20 2013
+++ src/sys/net/npf/npf_bpf.c Fri Dec 6 01:33:37 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_bpf.c,v 1.5 2013/11/23 19:32:20 rmind Exp $ */
+/* $NetBSD: npf_bpf.c,v 1.6 2013/12/06 01:33:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_bpf.c,v 1.5 2013/11/23 19:32:20 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_bpf.c,v 1.6 2013/12/06 01:33:37 rmind Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -157,6 +157,6 @@ npf_cop_table(bpf_ctx_t *bc, bpf_args_t
if ((t = npf_tableset_getbyid(tblset, tid)) == NULL) {
return 0;
}
- addr = (A & SRC_FLAG_BIT) ? npc->npc_srcip : npc->npc_dstip;
+ addr = npc->npc_ips[(A & SRC_FLAG_BIT) ? NPF_SRC : NPF_DST];
return npf_table_lookup(t, npc->npc_alen, addr) == 0;
}
Index: src/sys/net/npf/npf_impl.h
diff -u src/sys/net/npf/npf_impl.h:1.44 src/sys/net/npf/npf_impl.h:1.45
--- src/sys/net/npf/npf_impl.h:1.44 Wed Dec 4 01:38:49 2013
+++ src/sys/net/npf/npf_impl.h Fri Dec 6 01:33:37 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_impl.h,v 1.44 2013/12/04 01:38:49 rmind Exp $ */
+/* $NetBSD: npf_impl.h,v 1.45 2013/12/06 01:33:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -100,8 +100,12 @@ typedef bool (*npf_alg_func_t)(npf_cache
typedef npf_session_t *(*npf_alg_sfunc_t)(npf_cache_t *, nbuf_t *, int);
typedef void (*npf_workfunc_t)(void);
-/* Some artificial limits. */
+/*
+ * Some artificial limits.
+ * Note: very unlikely to have many ALGs.
+ */
#define NPF_MAX_RULES (1024 * 1024)
+#define NPF_MAX_ALGS 4
#define NPF_MAX_TABLES 128
#define NPF_MAX_RPROCS 128
#define NPF_MAX_IFMAP 64
@@ -184,9 +188,9 @@ int npf_packet_handler(void *, struct m
int npf_cache_all(npf_cache_t *, nbuf_t *);
void npf_recache(npf_cache_t *, nbuf_t *);
-bool npf_rwrip(const npf_cache_t *, int, const npf_addr_t *);
-bool npf_rwrport(const npf_cache_t *, int, const in_port_t);
-bool npf_rwrcksum(const npf_cache_t *, const int,
+bool npf_rwrip(const npf_cache_t *, u_int, const npf_addr_t *);
+bool npf_rwrport(const npf_cache_t *, u_int, const in_port_t);
+bool npf_rwrcksum(const npf_cache_t *, u_int,
const npf_addr_t *, const in_port_t);
uint16_t npf_fixup16_cksum(uint16_t, uint16_t, uint16_t);
@@ -327,8 +331,7 @@ bool npf_nat_sharepm(npf_natpolicy_t *,
void npf_nat_freealg(npf_natpolicy_t *, npf_alg_t *);
int npf_do_nat(npf_cache_t *, npf_session_t *, nbuf_t *, const int);
-int npf_nat_translate(npf_cache_t *, nbuf_t *, npf_nat_t *,
- const bool, const int);
+int npf_nat_translate(npf_cache_t *, nbuf_t *, npf_nat_t *, bool);
void npf_nat_destroy(npf_nat_t *);
void npf_nat_getorig(npf_nat_t *, npf_addr_t **, in_port_t *);
void npf_nat_gettrans(npf_nat_t *, npf_addr_t **, in_port_t *);
@@ -345,7 +348,7 @@ npf_alg_t * npf_alg_register(const char
int npf_alg_unregister(npf_alg_t *);
npf_alg_t * npf_alg_construct(const char *);
bool npf_alg_match(npf_cache_t *, nbuf_t *, npf_nat_t *, int);
-void npf_alg_exec(npf_cache_t *, nbuf_t *, npf_nat_t *, int);
+void npf_alg_exec(npf_cache_t *, nbuf_t *, npf_nat_t *, bool);
npf_session_t * npf_alg_session(npf_cache_t *, nbuf_t *, int);
/* Debugging routines. */
Index: src/sys/net/npf/npf_inet.c
diff -u src/sys/net/npf/npf_inet.c:1.27 src/sys/net/npf/npf_inet.c:1.28
--- src/sys/net/npf/npf_inet.c:1.27 Fri Nov 22 01:48:36 2013
+++ src/sys/net/npf/npf_inet.c Fri Dec 6 01:33:37 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_inet.c,v 1.27 2013/11/22 01:48:36 rmind Exp $ */
+/* $NetBSD: npf_inet.c,v 1.28 2013/12/06 01:33:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.27 2013/11/22 01:48:36 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.28 2013/12/06 01:33:37 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -338,8 +338,8 @@ npf_cache_ip(npf_cache_t *npc, nbuf_t *n
/* Cache: layer 3 - IPv4. */
npc->npc_alen = sizeof(struct in_addr);
- npc->npc_srcip = (npf_addr_t *)&ip->ip_src;
- npc->npc_dstip = (npf_addr_t *)&ip->ip_dst;
+ npc->npc_ips[NPF_SRC] = (npf_addr_t *)&ip->ip_src;
+ npc->npc_ips[NPF_DST] = (npf_addr_t *)&ip->ip_dst;
npc->npc_hlen = ip->ip_hl << 2;
npc->npc_proto = ip->ip_p;
@@ -413,8 +413,8 @@ npf_cache_ip(npf_cache_t *npc, nbuf_t *n
/* Cache: layer 3 - IPv6. */
npc->npc_alen = sizeof(struct in6_addr);
- npc->npc_srcip = (npf_addr_t *)&ip6->ip6_src;
- npc->npc_dstip = (npf_addr_t *)&ip6->ip6_dst;
+ npc->npc_ips[NPF_SRC] = (npf_addr_t *)&ip6->ip6_src;
+ npc->npc_ips[NPF_DST]= (npf_addr_t *)&ip6->ip6_dst;
npc->npc_ip.v6 = ip6;
flags |= NPC_IP6;
@@ -516,17 +516,12 @@ npf_recache(npf_cache_t *npc, nbuf_t *nb
* npf_rwrip: rewrite required IP address.
*/
bool
-npf_rwrip(const npf_cache_t *npc, int di, const npf_addr_t *addr)
+npf_rwrip(const npf_cache_t *npc, u_int which, const npf_addr_t *addr)
{
- npf_addr_t *oaddr;
-
KASSERT(npf_iscached(npc, NPC_IP46));
+ KASSERT(which == NPF_SRC || which == NPF_DST);
- /*
- * Rewrite source address if outgoing and destination if incoming.
- */
- oaddr = (di == PFIL_OUT) ? npc->npc_srcip : npc->npc_dstip;
- memcpy(oaddr, addr, npc->npc_alen);
+ memcpy(npc->npc_ips[which], addr, npc->npc_alen);
return true;
}
@@ -534,21 +529,22 @@ npf_rwrip(const npf_cache_t *npc, int di
* npf_rwrport: rewrite required TCP/UDP port.
*/
bool
-npf_rwrport(const npf_cache_t *npc, int di, const in_port_t port)
+npf_rwrport(const npf_cache_t *npc, u_int which, const in_port_t port)
{
const int proto = npc->npc_proto;
in_port_t *oport;
KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
KASSERT(proto == IPPROTO_TCP || proto == IPPROTO_UDP);
+ KASSERT(which == NPF_SRC || which == NPF_DST);
/* Get the offset and store the port in it. */
if (proto == IPPROTO_TCP) {
struct tcphdr *th = npc->npc_l4.tcp;
- oport = (di == PFIL_OUT) ? &th->th_sport : &th->th_dport;
+ oport = (which == NPF_SRC) ? &th->th_sport : &th->th_dport;
} else {
struct udphdr *uh = npc->npc_l4.udp;
- oport = (di == PFIL_OUT) ? &uh->uh_sport : &uh->uh_dport;
+ oport = (which == NPF_SRC) ? &uh->uh_sport : &uh->uh_dport;
}
memcpy(oport, &port, sizeof(in_port_t));
return true;
@@ -558,17 +554,17 @@ npf_rwrport(const npf_cache_t *npc, int
* npf_rwrcksum: rewrite IPv4 and/or TCP/UDP checksum.
*/
bool
-npf_rwrcksum(const npf_cache_t *npc, const int di,
+npf_rwrcksum(const npf_cache_t *npc, u_int which,
const npf_addr_t *addr, const in_port_t port)
{
+ const npf_addr_t *oaddr = npc->npc_ips[which];
const int proto = npc->npc_proto;
const int alen = npc->npc_alen;
- npf_addr_t *oaddr;
uint16_t *ocksum;
in_port_t oport;
KASSERT(npf_iscached(npc, NPC_LAYER4));
- oaddr = (di == PFIL_OUT) ? npc->npc_srcip : npc->npc_dstip;
+ KASSERT(which == NPF_SRC || which == NPF_DST);
if (npf_iscached(npc, NPC_IP4)) {
struct ip *ip = npc->npc_ip.v4;
@@ -597,7 +593,7 @@ npf_rwrcksum(const npf_cache_t *npc, con
struct tcphdr *th = npc->npc_l4.tcp;
ocksum = &th->th_sum;
- oport = (di == PFIL_OUT) ? th->th_sport : th->th_dport;
+ oport = (which == NPF_SRC) ? th->th_sport : th->th_dport;
} else {
struct udphdr *uh = npc->npc_l4.udp;
@@ -607,7 +603,7 @@ npf_rwrcksum(const npf_cache_t *npc, con
/* No need to update. */
return true;
}
- oport = (di == PFIL_OUT) ? uh->uh_sport : uh->uh_dport;
+ oport = (which == NPF_SRC) ? uh->uh_sport : uh->uh_dport;
}
uint16_t cksum = npf_addr_cksum(*ocksum, alen, oaddr, addr);
Index: src/sys/net/npf/npf_nat.c
diff -u src/sys/net/npf/npf_nat.c:1.22 src/sys/net/npf/npf_nat.c:1.23
--- src/sys/net/npf/npf_nat.c:1.22 Wed Dec 4 01:38:49 2013
+++ src/sys/net/npf/npf_nat.c Fri Dec 6 01:33:37 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_nat.c,v 1.22 2013/12/04 01:38:49 rmind Exp $ */
+/* $NetBSD: npf_nat.c,v 1.23 2013/12/06 01:33:37 rmind Exp $ */
/*-
* Copyright (c) 2010-2013 The NetBSD Foundation, Inc.
@@ -43,14 +43,8 @@
*
* There are two types of translation: outbound (NPF_NATOUT) and
* inbound (NPF_NATIN). It should not be confused with connection
- * direction.
- *
- * Outbound NAT rewrites:
- * - Source on "forwards" stream.
- * - Destination on "backwards" stream.
- * Inbound NAT rewrites:
- * - Destination on "forwards" stream.
- * - Source on "backwards" stream.
+ * direction. See npf_nat_which() for the description of how the
+ * addresses are rewritten.
*
* It should be noted that bi-directional NAT is a combined outbound
* and inbound translation, therefore constructed as two policies.
@@ -76,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.22 2013/12/04 01:38:49 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.23 2013/12/06 01:33:37 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -160,7 +154,6 @@ static pool_cache_t nat_cache __read_mo
void
npf_nat_sysinit(void)
{
-
nat_cache = pool_cache_init(sizeof(npf_nat_t), coherency_unit,
0, 0, "npfnatpl", NULL, IPL_NET, NULL, NULL, NULL);
KASSERT(nat_cache != NULL);
@@ -169,8 +162,7 @@ npf_nat_sysinit(void)
void
npf_nat_sysfini(void)
{
-
- /* NAT policies should already be destroyed. */
+ /* All NAT policies should already be destroyed. */
pool_cache_destroy(nat_cache);
}
@@ -178,7 +170,6 @@ npf_nat_sysfini(void)
* npf_nat_newpolicy: create a new NAT policy.
*
* => Shares portmap if policy is on existing translation address.
- * => XXX: serialise at upper layer.
*/
npf_natpolicy_t *
npf_nat_newpolicy(prop_dictionary_t natdict, npf_ruleset_t *nrlset)
@@ -424,6 +415,29 @@ npf_nat_putport(npf_natpolicy_t *np, in_
}
/*
+ * npf_nat_which: tell which address (source or destination) should be
+ * rewritten given the combination of the NAT type and flow direction.
+ */
+static inline u_int
+npf_nat_which(const int type, bool forw)
+{
+ /*
+ * Outbound NAT rewrites:
+ * - Source on "forwards" stream.
+ * - Destination on "backwards" stream.
+ * Inbound NAT is other way round.
+ */
+ if (type == NPF_NATOUT) {
+ forw = !forw;
+ } else {
+ KASSERT(type == NPF_NATIN);
+ }
+ CTASSERT(NPF_SRC == 0 && NPF_DST == 1);
+ KASSERT(forw == 0 || forw == 1);
+ return (u_int)forw;
+}
+
+/*
* npf_nat_inspect: inspect packet against NAT ruleset and return a policy.
*
* => Acquire a reference on the policy, if found.
@@ -471,12 +485,12 @@ npf_nat_create(npf_cache_t *npc, npf_nat
/* Save the original address which may be rewritten. */
if (np->n_type == NPF_NATOUT) {
- /* Source (local) for Outbound NAT. */
- memcpy(&nt->nt_oaddr, npc->npc_srcip, npc->npc_alen);
+ /* Outbound NAT: source (think internal) address. */
+ memcpy(&nt->nt_oaddr, npc->npc_ips[NPF_SRC], npc->npc_alen);
} else {
- /* Destination (external) for Inbound NAT. */
+ /* Inbound NAT: destination (think external) address. */
KASSERT(np->n_type == NPF_NATIN);
- memcpy(&nt->nt_oaddr, npc->npc_dstip, npc->npc_alen);
+ memcpy(&nt->nt_oaddr, npc->npc_ips[NPF_DST], npc->npc_alen);
}
/*
@@ -517,16 +531,17 @@ out:
* npf_nat_translate: perform address and/or port translation.
*/
int
-npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt,
- const bool forw, const int di)
+npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw)
{
const int proto = npc->npc_proto;
const npf_natpolicy_t *np = nt->nt_natpolicy;
+ const u_int which = npf_nat_which(np->n_type, forw);
const npf_addr_t *addr;
in_port_t port;
KASSERT(npf_iscached(npc, NPC_IP46));
KASSERT(npf_iscached(npc, NPC_LAYER4));
+ KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
if (forw) {
/* "Forwards" stream: use translation address/port. */
@@ -539,33 +554,24 @@ npf_nat_translate(npf_cache_t *npc, nbuf
}
KASSERT((np->n_flags & NPF_NAT_PORTS) != 0 || port == 0);
- /* Process delayed checksums (XXX: NetBSD). */
- if (nbuf_cksum_barrier(nbuf, di)) {
- npf_recache(npc, nbuf);
- }
- KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
-
/* Execute ALG hook first. */
if ((npc->npc_info & NPC_ALG_EXEC) == 0) {
npc->npc_info |= NPC_ALG_EXEC;
- npf_alg_exec(npc, nbuf, nt, di);
+ npf_alg_exec(npc, nbuf, nt, forw);
}
/*
- * Rewrite IP and/or TCP/UDP checksums first, since it will use
- * the cache containing original values for checksum calculation.
+ * Rewrite IP and/or TCP/UDP checksums first, since we need the
+ * current (old) address/port for the calculations. Then perform
+ * the address translation i.e. rewrite source or destination.
*/
- if (!npf_rwrcksum(npc, di, addr, port)) {
+ if (!npf_rwrcksum(npc, which, addr, port)) {
return EINVAL;
}
-
- /*
- * Address translation: rewrite source/destination address, depending
- * on direction (PFIL_OUT - for source, PFIL_IN - for destination).
- */
- if (!npf_rwrip(npc, di, addr)) {
+ if (!npf_rwrip(npc, which, addr)) {
return EINVAL;
}
+
if ((np->n_flags & NPF_NAT_PORTS) == 0) {
/* Done. */
return 0;
@@ -574,9 +580,8 @@ npf_nat_translate(npf_cache_t *npc, nbuf
switch (proto) {
case IPPROTO_TCP:
case IPPROTO_UDP:
- KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
/* Rewrite source/destination port. */
- if (!npf_rwrport(npc, di, port)) {
+ if (!npf_rwrport(npc, which, port)) {
return EINVAL;
}
break;
@@ -675,8 +680,13 @@ npf_do_nat(npf_cache_t *npc, npf_session
}
translate:
+ /* May need to process the delayed checksums first (XXX: NetBSD). */
+ if (nbuf_cksum_barrier(nbuf, di)) {
+ npf_recache(npc, nbuf);
+ }
+
/* Perform the translation. */
- error = npf_nat_translate(npc, nbuf, nt, forw, di);
+ error = npf_nat_translate(npc, nbuf, nt, forw);
out:
if (error && nse) {
/* It created for NAT - just expire. */
Index: src/sys/net/npf/npf_session.c
diff -u src/sys/net/npf/npf_session.c:1.29 src/sys/net/npf/npf_session.c:1.30
--- src/sys/net/npf/npf_session.c:1.29 Wed Dec 4 01:38:49 2013
+++ src/sys/net/npf/npf_session.c Fri Dec 6 01:33:37 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_session.c,v 1.29 2013/12/04 01:38:49 rmind Exp $ */
+/* $NetBSD: npf_session.c,v 1.30 2013/12/06 01:33:37 rmind Exp $ */
/*-
* Copyright (c) 2010-2013 The NetBSD Foundation, Inc.
@@ -92,7 +92,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.29 2013/12/04 01:38:49 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_session.c,v 1.30 2013/12/06 01:33:37 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -494,9 +494,11 @@ npf_session_lookup(const npf_cache_t *np
if (!npf_session_fillent(npc, &senkey)) {
return NULL;
}
- KASSERT(npc->npc_srcip && npc->npc_dstip && npc->npc_alen > 0);
- memcpy(&senkey.se_src_addr, npc->npc_srcip, npc->npc_alen);
- memcpy(&senkey.se_dst_addr, npc->npc_dstip, npc->npc_alen);
+ KASSERT(npc->npc_ips[NPF_SRC] && npc->npc_ips[NPF_DST]);
+ KASSERT(npc->npc_alen > 0);
+
+ memcpy(&senkey.se_src_addr, npc->npc_ips[NPF_SRC], npc->npc_alen);
+ memcpy(&senkey.se_dst_addr, npc->npc_ips[NPF_DST], npc->npc_alen);
senkey.se_alen = npc->npc_alen;
/*
@@ -638,8 +640,8 @@ npf_session_establish(npf_cache_t *npc,
KASSERT(npf_iscached(npc, NPC_IP46));
alen = npc->npc_alen;
fw = &se->s_forw_entry;
- memcpy(&fw->se_src_addr, npc->npc_srcip, alen);
- memcpy(&fw->se_dst_addr, npc->npc_dstip, alen);
+ memcpy(&fw->se_src_addr, npc->npc_ips[NPF_SRC], alen);
+ memcpy(&fw->se_dst_addr, npc->npc_ips[NPF_DST], alen);
/* Protocol and interface. */
memset(&se->s_common_id, 0, sizeof(npf_secomid_t));
@@ -978,6 +980,7 @@ again:
bool removed = (se->s_flags & SE_REMOVED) == SE_REMOVED;
nse = LIST_NEXT(se, s_list);
+ KASSERT((se->s_flags & SE_EXPIRE) != 0);
if (removed && se->s_refcnt == 0) {
/* Destroy only if removed and no references. */
LIST_REMOVE(se, s_list);