Module Name: src
Committed By: rmind
Date: Thu Feb 13 03:34:41 UTC 2014
Modified Files:
src/lib/libnpf: npf.c npf.h
src/sys/net/npf: npf.h npf_impl.h npf_inet.c npf_nat.c
src/usr.sbin/npf/npfctl: npf_build.c npf_data.c npf_parse.y npf_scan.l
npfctl.h
src/usr.sbin/npf/npftest: npftest.c npftest.conf npftest.h
src/usr.sbin/npf/npftest/libnpftest: npf_mbuf_subr.c npf_nat_test.c
npf_test.h npf_test_subr.c
Log Message:
NPF: add support for IPv6-to-IPv6 Network Prefix Translation (NPTv6),
as per RFC 6296. Add a unit test. Also, bump NPF_VERSION.
Thanks to S.P.Zeidler for the help with NPTv6 work!
To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 src/lib/libnpf/npf.c
cvs rdiff -u -r1.24 -r1.25 src/lib/libnpf/npf.h
cvs rdiff -u -r1.36 -r1.37 src/sys/net/npf/npf.h
cvs rdiff -u -r1.46 -r1.47 src/sys/net/npf/npf_impl.h
cvs rdiff -u -r1.28 -r1.29 src/sys/net/npf/npf_inet.c
cvs rdiff -u -r1.24 -r1.25 src/sys/net/npf/npf_nat.c
cvs rdiff -u -r1.35 -r1.36 src/usr.sbin/npf/npfctl/npf_build.c \
src/usr.sbin/npf/npfctl/npfctl.h
cvs rdiff -u -r1.24 -r1.25 src/usr.sbin/npf/npfctl/npf_data.c
cvs rdiff -u -r1.31 -r1.32 src/usr.sbin/npf/npfctl/npf_parse.y
cvs rdiff -u -r1.18 -r1.19 src/usr.sbin/npf/npfctl/npf_scan.l
cvs rdiff -u -r1.16 -r1.17 src/usr.sbin/npf/npftest/npftest.c
cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/npf/npftest/npftest.conf
cvs rdiff -u -r1.12 -r1.13 src/usr.sbin/npf/npftest/npftest.h
cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c
cvs rdiff -u -r1.14 -r1.15 src/usr.sbin/npf/npftest/libnpftest/npf_test.h
cvs rdiff -u -r1.8 -r1.9 src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libnpf/npf.c
diff -u src/lib/libnpf/npf.c:1.27 src/lib/libnpf/npf.c:1.28
--- src/lib/libnpf/npf.c:1.27 Fri Feb 7 23:45:22 2014
+++ src/lib/libnpf/npf.c Thu Feb 13 03:34:41 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf.c,v 1.27 2014/02/07 23:45:22 rmind Exp $ */
+/* $NetBSD: npf.c,v 1.28 2014/02/13 03:34:41 rmind Exp $ */
/*-
* Copyright (c) 2010-2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.27 2014/02/07 23:45:22 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.28 2014/02/13 03:34:41 rmind Exp $");
#include <sys/types.h>
#include <netinet/in_systm.h>
@@ -802,7 +802,7 @@ npf_rproc_getname(nl_rproc_t *rp)
nl_nat_t *
npf_nat_create(int type, u_int flags, const char *ifname,
- npf_addr_t *addr, int af, in_port_t port)
+ int af, npf_addr_t *addr, npf_netmask_t mask, in_port_t port)
{
nl_rule_t *rl;
prop_dictionary_t rldict;
@@ -832,13 +832,14 @@ npf_nat_create(int type, u_int flags, co
prop_dictionary_set_int32(rldict, "type", type);
prop_dictionary_set_uint32(rldict, "flags", flags);
- /* Translation IP. */
+ /* Translation IP and mask. */
addrdat = prop_data_create_data(addr, sz);
if (addrdat == NULL) {
npf_rule_destroy(rl);
return NULL;
}
prop_dictionary_set(rldict, "translation-ip", addrdat);
+ prop_dictionary_set_uint32(rldict, "translation-mask", mask);
prop_object_release(addrdat);
/* Translation port (for redirect case). */
@@ -865,6 +866,27 @@ npf_nat_iterate(nl_config_t *ncf)
}
int
+npf_nat_setalgo(nl_nat_t *nt, u_int algo)
+{
+ prop_dictionary_t rldict = nt->nrl_dict;
+ prop_dictionary_set_uint32(rldict, "translation-algo", algo);
+ return 0;
+}
+
+int
+npf_nat_setnpt66(nl_nat_t *nt, uint16_t adj)
+{
+ prop_dictionary_t rldict = nt->nrl_dict;
+ int error;
+
+ if ((error = npf_nat_setalgo(nt, NPF_ALGO_NPT66)) != 0) {
+ return error;
+ }
+ prop_dictionary_set_uint16(rldict, "npt66-adjustment", adj);
+ return 0;
+}
+
+int
npf_nat_gettype(nl_nat_t *nt)
{
prop_dictionary_t rldict = nt->nrl_dict;
Index: src/lib/libnpf/npf.h
diff -u src/lib/libnpf/npf.h:1.24 src/lib/libnpf/npf.h:1.25
--- src/lib/libnpf/npf.h:1.24 Fri Feb 7 23:45:22 2014
+++ src/lib/libnpf/npf.h Thu Feb 13 03:34:41 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf.h,v 1.24 2014/02/07 23:45:22 rmind Exp $ */
+/* $NetBSD: npf.h,v 1.25 2014/02/13 03:34:41 rmind Exp $ */
/*-
- * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -105,7 +105,7 @@ bool npf_rproc_exists_p(nl_config_t *,
int npf_rproc_insert(nl_config_t *, nl_rproc_t *);
nl_nat_t * npf_nat_create(int, u_int, const char *,
- npf_addr_t *, int, in_port_t);
+ int, npf_addr_t *, npf_netmask_t, in_port_t);
int npf_nat_insert(nl_config_t *, nl_nat_t *, pri_t);
nl_table_t * npf_table_create(const char *, u_int, int);
@@ -139,6 +139,9 @@ int npf_nat_gettype(nl_nat_t *);
unsigned npf_nat_getflags(nl_nat_t *);
void npf_nat_getmap(nl_nat_t *, npf_addr_t *, size_t *, in_port_t *);
+int npf_nat_setalgo(nl_nat_t *, u_int);
+int npf_nat_setnpt66(nl_nat_t *, uint16_t);
+
nl_rproc_t * npf_rproc_iterate(nl_config_t *);
const char * npf_rproc_getname(nl_rproc_t *);
Index: src/sys/net/npf/npf.h
diff -u src/sys/net/npf/npf.h:1.36 src/sys/net/npf/npf.h:1.37
--- src/sys/net/npf/npf.h:1.36 Fri Feb 7 23:45:22 2014
+++ src/sys/net/npf/npf.h Thu Feb 13 03:34:40 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf.h,v 1.36 2014/02/07 23:45:22 rmind Exp $ */
+/* $NetBSD: npf.h,v 1.37 2014/02/13 03:34:40 rmind Exp $ */
/*-
- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -45,7 +45,7 @@
#include <netinet/in_systm.h>
#include <netinet/in.h>
-#define NPF_VERSION 12
+#define NPF_VERSION 13
/*
* Public declarations and definitions.
@@ -237,6 +237,8 @@ bool npf_autounload_p(void);
#define NPF_NAT_PORTMAP 0x02
#define NPF_NAT_STATIC 0x04
+#define NPF_ALGO_NPT66 1
+
/* Table types. */
#define NPF_TABLE_HASH 1
#define NPF_TABLE_TREE 2
Index: src/sys/net/npf/npf_impl.h
diff -u src/sys/net/npf/npf_impl.h:1.46 src/sys/net/npf/npf_impl.h:1.47
--- src/sys/net/npf/npf_impl.h:1.46 Thu Feb 6 02:51:28 2014
+++ src/sys/net/npf/npf_impl.h Thu Feb 13 03:34:40 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_impl.h,v 1.46 2014/02/06 02:51:28 rmind Exp $ */
+/* $NetBSD: npf_impl.h,v 1.47 2014/02/13 03:34:40 rmind Exp $ */
/*-
- * Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -192,6 +192,8 @@ bool npf_rwrip(const npf_cache_t *, u_i
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);
+int npf_npt66_rwr(const npf_cache_t *, u_int, const npf_addr_t *,
+ npf_netmask_t, uint16_t);
uint16_t npf_fixup16_cksum(uint16_t, uint16_t, uint16_t);
uint16_t npf_fixup32_cksum(uint16_t, uint32_t, uint32_t);
Index: src/sys/net/npf/npf_inet.c
diff -u src/sys/net/npf/npf_inet.c:1.28 src/sys/net/npf/npf_inet.c:1.29
--- src/sys/net/npf/npf_inet.c:1.28 Fri Dec 6 01:33:37 2013
+++ src/sys/net/npf/npf_inet.c Thu Feb 13 03:34:40 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_inet.c,v 1.28 2013/12/06 01:33:37 rmind Exp $ */
+/* $NetBSD: npf_inet.c,v 1.29 2014/02/13 03:34:40 rmind Exp $ */
/*-
- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This material is based upon work partially supported by The
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.28 2013/12/06 01:33:37 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.29 2014/02/13 03:34:40 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -616,6 +616,79 @@ npf_rwrcksum(const npf_cache_t *npc, u_i
return true;
}
+/*
+ * IPv6-to-IPv6 Network Prefix Translation (NPTv6), as per RFC 6296.
+ */
+
+int
+npf_npt66_rwr(const npf_cache_t *npc, u_int which, const npf_addr_t *pref,
+ npf_netmask_t len, uint16_t adj)
+{
+ npf_addr_t *addr = npc->npc_ips[which];
+ unsigned remnant, word, preflen = len >> 4;
+ uint32_t sum;
+
+ KASSERT(which == NPF_SRC || which == NPF_DST);
+
+ if (!npf_iscached(npc, NPC_IP6)) {
+ return EINVAL;
+ }
+ if (len <= 48) {
+ /*
+ * The word to adjust. Cannot translate the 0xffff
+ * subnet if /48 or shorter.
+ */
+ word = 3;
+ if (addr->s6_addr16[word] == 0xffff) {
+ return EINVAL;
+ }
+ } else {
+ /*
+ * Also, all 0s or 1s in the host part are disallowed for
+ * longer than /48 prefixes.
+ */
+ if ((addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0) ||
+ (addr->s6_addr32[2] == ~0U && addr->s6_addr32[3] == ~0U))
+ return EINVAL;
+
+ /* Determine the 16-bit word to adjust. */
+ for (word = 4; word < 8; word++)
+ if (addr->s6_addr16[word] != 0xffff)
+ break;
+ }
+
+ /* Rewrite the prefix. */
+ for (unsigned i = 0; i < preflen; i++) {
+ addr->s6_addr16[i] = pref->s6_addr16[i];
+ }
+
+ /*
+ * If prefix length is within a 16-bit word (not dividable by 16),
+ * then prepare a mask, determine the word and adjust it.
+ */
+ if ((remnant = len - (preflen << 4)) != 0) {
+ const uint16_t wordmask = (1U << remnant) - 1;
+ const unsigned i = preflen;
+
+ addr->s6_addr16[i] = (pref->s6_addr16[i] & wordmask) |
+ (addr->s6_addr16[i] & ~wordmask);
+ }
+
+ /*
+ * Performing 1's complement sum/difference.
+ */
+ sum = addr->s6_addr16[word] + adj;
+ while (sum >> 16) {
+ sum = (sum >> 16) + (sum & 0xffff);
+ }
+ if (sum == 0xffff) {
+ /* RFC 1071. */
+ sum = 0x0000;
+ }
+ addr->s6_addr16[word] = sum;
+ return 0;
+}
+
#if defined(DDB) || defined(_NPF_TESTING)
void
Index: src/sys/net/npf/npf_nat.c
diff -u src/sys/net/npf/npf_nat.c:1.24 src/sys/net/npf/npf_nat.c:1.25
--- src/sys/net/npf/npf_nat.c:1.24 Fri Feb 7 23:45:22 2014
+++ src/sys/net/npf/npf_nat.c Thu Feb 13 03:34:40 2014
@@ -1,6 +1,7 @@
-/* $NetBSD: npf_nat.c,v 1.24 2014/02/07 23:45:22 rmind Exp $ */
+/* $NetBSD: npf_nat.c,v 1.25 2014/02/13 03:34:40 rmind Exp $ */
/*-
+ * Copyright (c) 2014 Mindaugas Rasiukevicius <rmind at netbsd org>
* Copyright (c) 2010-2013 The NetBSD Foundation, Inc.
* All rights reserved.
*
@@ -70,7 +71,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.24 2014/02/07 23:45:22 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.25 2014/02/13 03:34:40 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -100,7 +101,7 @@ typedef struct {
/* Portmap range: [ 1024 .. 65535 ] */
#define PORTMAP_FIRST (1024)
#define PORTMAP_SIZE ((65536 - PORTMAP_FIRST) / 32)
-#define PORTMAP_FILLED ((uint32_t)~0)
+#define PORTMAP_FILLED ((uint32_t)~0U)
#define PORTMAP_MASK (31)
#define PORTMAP_SHIFT (5)
@@ -121,7 +122,12 @@ struct npf_natpolicy {
u_int n_flags;
size_t n_addr_sz;
npf_addr_t n_taddr;
+ npf_netmask_t n_tmask;
in_port_t n_tport;
+ u_int n_algo;
+ union {
+ uint16_t n_npt66_adj;
+ };
};
#define NPF_NP_CMP_START offsetof(npf_natpolicy_t, n_type)
@@ -186,22 +192,34 @@ npf_nat_newpolicy(prop_dictionary_t natd
/* Should be exclusively either inbound or outbound NAT. */
if (((np->n_type == NPF_NATIN) ^ (np->n_type == NPF_NATOUT)) == 0) {
- kmem_free(np, sizeof(npf_natpolicy_t));
- return NULL;
+ goto err;
}
mutex_init(&np->n_lock, MUTEX_DEFAULT, IPL_SOFTNET);
cv_init(&np->n_cv, "npfnatcv");
LIST_INIT(&np->n_nat_list);
- /* Translation IP. */
+ /* Translation IP, mask and port (if applicable). */
obj = prop_dictionary_get(natdict, "translation-ip");
np->n_addr_sz = prop_data_size(obj);
- KASSERT(np->n_addr_sz > 0 && np->n_addr_sz <= sizeof(npf_addr_t));
+ if (np->n_addr_sz == 0 || np->n_addr_sz > sizeof(npf_addr_t)) {
+ goto err;
+ }
memcpy(&np->n_taddr, prop_data_data_nocopy(obj), np->n_addr_sz);
-
- /* Translation port (for redirect case). */
+ prop_dictionary_get_uint8(natdict, "translation-mask", &np->n_tmask);
prop_dictionary_get_uint16(natdict, "translation-port", &np->n_tport);
+ prop_dictionary_get_uint32(natdict, "translation-algo", &np->n_algo);
+ switch (np->n_algo) {
+ case NPF_ALGO_NPT66:
+ prop_dictionary_get_uint16(natdict, "npt66-adjustment",
+ &np->n_npt66_adj);
+ break;
+ default:
+ if (np->n_tmask != NPF_NO_NETMASK)
+ goto err;
+ break;
+ }
+
/* Determine if port map is needed. */
np->n_portmap = NULL;
if ((np->n_flags & NPF_NAT_PORTMAP) == 0) {
@@ -223,6 +241,9 @@ npf_nat_newpolicy(prop_dictionary_t natd
KASSERT(np->n_portmap != NULL);
}
return np;
+err:
+ kmem_free(np, sizeof(npf_natpolicy_t));
+ return NULL;
}
/*
@@ -607,6 +628,29 @@ npf_nat_translate(npf_cache_t *npc, nbuf
}
/*
+ * npf_nat_algo: perform the translation given the algorithm.
+ */
+static inline int
+npf_nat_algo(npf_cache_t *npc, const npf_natpolicy_t *np, bool forw)
+{
+ u_int which;
+ int error;
+
+ switch (np->n_algo) {
+ case NPF_ALGO_NPT66:
+ which = npf_nat_which(np->n_type, forw);
+ error = npf_npt66_rwr(npc, which, &np->n_taddr,
+ np->n_tmask, np->n_npt66_adj);
+ break;
+ default:
+ error = npf_nat_rwr(npc, np, &np->n_taddr, np->n_tport, forw);
+ break;
+ }
+
+ return error;
+}
+
+/*
* npf_do_nat:
* - Inspect packet for a NAT policy, unless a session with a NAT
* association already exists. In such case, determine whether it
@@ -656,7 +700,7 @@ npf_do_nat(npf_cache_t *npc, npf_session
if (nbuf_cksum_barrier(nbuf, di)) {
npf_recache(npc, nbuf);
}
- error = npf_nat_rwr(npc, np, &np->n_taddr, np->n_tport, forw);
+ error = npf_nat_algo(npc, np, forw);
atomic_dec_uint(&np->n_refcnt);
return error;
}
Index: src/usr.sbin/npf/npfctl/npf_build.c
diff -u src/usr.sbin/npf/npfctl/npf_build.c:1.35 src/usr.sbin/npf/npfctl/npf_build.c:1.36
--- src/usr.sbin/npf/npfctl/npf_build.c:1.35 Fri Feb 7 23:45:22 2014
+++ src/usr.sbin/npf/npfctl/npf_build.c Thu Feb 13 03:34:40 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_build.c,v 1.35 2014/02/07 23:45:22 rmind Exp $ */
+/* $NetBSD: npf_build.c,v 1.36 2014/02/13 03:34:40 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.35 2014/02/07 23:45:22 rmind Exp $");
+__RCSID("$NetBSD: npf_build.c,v 1.36 2014/02/13 03:34:40 rmind Exp $");
#include <sys/types.h>
#include <sys/mman.h>
@@ -533,24 +533,15 @@ npfctl_build_rule(uint32_t attr, const c
* npfctl_build_nat: create a single NAT policy of a specified
* type with a given filter options.
*/
-static void
-npfctl_build_nat(int type, const char *ifname, sa_family_t family,
- const addr_port_t *ap, const filt_opts_t *fopts, u_int flags)
+static nl_nat_t *
+npfctl_build_nat(int type, const char *ifname, const addr_port_t *ap,
+ const filt_opts_t *fopts, u_int flags)
{
const opt_proto_t op = { .op_proto = -1, .op_opts = NULL };
- fam_addr_mask_t *am;
+ fam_addr_mask_t *am = npfctl_get_singlefam(ap->ap_netaddr);
in_port_t port;
nl_nat_t *nat;
- if (!ap->ap_netaddr) {
- yyerror("%s network segment is not specified",
- type == NPF_NATIN ? "inbound" : "outbound");
- }
- am = npfctl_get_singlefam(ap->ap_netaddr);
- if (am->fam_family != family) {
- yyerror("IPv6 NAT is not supported");
- }
-
if (ap->ap_portrange) {
port = npfctl_get_singleport(ap->ap_portrange);
flags &= ~NPF_NAT_PORTMAP;
@@ -559,10 +550,11 @@ npfctl_build_nat(int type, const char *i
port = 0;
}
- nat = npf_nat_create(type, flags, ifname,
- &am->fam_addr, am->fam_family, port);
- npfctl_build_code(nat, family, &op, fopts);
+ nat = npf_nat_create(type, flags, ifname, am->fam_family,
+ &am->fam_addr, am->fam_mask, port);
+ npfctl_build_code(nat, am->fam_family, &op, fopts);
npf_nat_insert(npf_conf, nat, NPF_PRI_LAST);
+ return nat;
}
/*
@@ -571,10 +563,12 @@ npfctl_build_nat(int type, const char *i
void
npfctl_build_natseg(int sd, int type, const char *ifname,
const addr_port_t *ap1, const addr_port_t *ap2,
- const filt_opts_t *fopts)
+ const filt_opts_t *fopts, u_int algo)
{
- sa_family_t af = AF_INET;
+ fam_addr_mask_t *am1 = NULL, *am2 = NULL;
+ nl_nat_t *nt1 = NULL, *nt2 = NULL;
filt_opts_t imfopts;
+ uint16_t adj = 0;
u_int flags;
bool binat;
@@ -603,6 +597,38 @@ npfctl_build_natseg(int sd, int type, co
}
/*
+ * Validate the mappings and their configuration.
+ */
+
+ if ((type & NPF_NATIN) != 0) {
+ if (!ap1->ap_netaddr)
+ yyerror("inbound network segment is not specified");
+ am1 = npfctl_get_singlefam(ap1->ap_netaddr);
+ }
+ if ((type & NPF_NATOUT) != 0) {
+ if (!ap2->ap_netaddr)
+ yyerror("outbound network segment is not specified");
+ am2 = npfctl_get_singlefam(ap2->ap_netaddr);
+ }
+
+ switch (algo) {
+ case NPF_ALGO_NPT66:
+ if (am1 == NULL || am2 == NULL)
+ yyerror("1:1 mapping of two segments must be "
+ "used for NPTv6");
+ if (am1->fam_mask != am2->fam_mask)
+ yyerror("asymmetric translation is not supported");
+ adj = npfctl_npt66_calcadj(am1->fam_mask,
+ &am1->fam_addr, &am2->fam_addr);
+ break;
+ default:
+ if ((am1 && am1->fam_mask != NPF_NO_NETMASK) ||
+ (am2 && am2->fam_mask != NPF_NO_NETMASK))
+ yyerror("net-to-net translation is not supported");
+ break;
+ }
+
+ /*
* If the filter criteria is not specified explicitly, apply implicit
* filtering according to the given network segments.
*
@@ -615,12 +641,17 @@ npfctl_build_natseg(int sd, int type, co
if (type & NPF_NATIN) {
memset(&imfopts, 0, sizeof(filt_opts_t));
memcpy(&imfopts.fo_to, ap2, sizeof(addr_port_t));
- npfctl_build_nat(NPF_NATIN, ifname, af, ap1, fopts, flags);
+ nt1 = npfctl_build_nat(NPF_NATIN, ifname, ap1, fopts, flags);
}
if (type & NPF_NATOUT) {
memset(&imfopts, 0, sizeof(filt_opts_t));
memcpy(&imfopts.fo_from, ap1, sizeof(addr_port_t));
- npfctl_build_nat(NPF_NATOUT, ifname, af, ap2, fopts, flags);
+ nt2 = npfctl_build_nat(NPF_NATOUT, ifname, ap2, fopts, flags);
+ }
+
+ if (algo == NPF_ALGO_NPT66) {
+ npf_nat_setnpt66(nt1, ~adj);
+ npf_nat_setnpt66(nt2, adj);
}
}
Index: src/usr.sbin/npf/npfctl/npfctl.h
diff -u src/usr.sbin/npf/npfctl/npfctl.h:1.35 src/usr.sbin/npf/npfctl/npfctl.h:1.36
--- src/usr.sbin/npf/npfctl/npfctl.h:1.35 Mon Feb 3 02:21:52 2014
+++ src/usr.sbin/npf/npfctl/npfctl.h Thu Feb 13 03:34:40 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npfctl.h,v 1.35 2014/02/03 02:21:52 rmind Exp $ */
+/* $NetBSD: npfctl.h,v 1.36 2014/02/13 03:34:40 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -126,6 +126,8 @@ npfvar_t * npfctl_parse_port_range_varia
npfvar_t * npfctl_parse_fam_addr_mask(const char *, const char *,
unsigned long *);
bool npfctl_parse_cidr(char *, fam_addr_mask_t *, int *);
+uint16_t npfctl_npt66_calcadj(npf_netmask_t, const npf_addr_t *,
+ const npf_addr_t *);
/*
* NPF extension loading.
@@ -193,7 +195,7 @@ void npfctl_build_rule(uint32_t, const
const char *, const char *);
void npfctl_build_natseg(int, int, const char *,
const addr_port_t *, const addr_port_t *,
- const filt_opts_t *);
+ const filt_opts_t *, unsigned);
void npfctl_build_maprset(const char *, int, const char *);
void npfctl_build_table(const char *, u_int, const char *);
Index: src/usr.sbin/npf/npfctl/npf_data.c
diff -u src/usr.sbin/npf/npfctl/npf_data.c:1.24 src/usr.sbin/npf/npfctl/npf_data.c:1.25
--- src/usr.sbin/npf/npfctl/npf_data.c:1.24 Mon Feb 3 02:21:52 2014
+++ src/usr.sbin/npf/npfctl/npf_data.c Thu Feb 13 03:34:40 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_data.c,v 1.24 2014/02/03 02:21:52 rmind Exp $ */
+/* $NetBSD: npf_data.c,v 1.25 2014/02/13 03:34:40 rmind Exp $ */
/*-
- * Copyright (c) 2009-2012 The NetBSD Foundation, Inc.
+ * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: npf_data.c,v 1.24 2014/02/03 02:21:52 rmind Exp $");
+__RCSID("$NetBSD: npf_data.c,v 1.25 2014/02/13 03:34:40 rmind Exp $");
#include <sys/types.h>
#include <sys/null.h>
@@ -585,3 +585,49 @@ out:
npfvar_destroy(vp);
return NULL;
}
+
+/*
+ * npfctl_npt66_calcadj: calculate the adjustment for NPTv6 as per RFC 6296.
+ */
+uint16_t
+npfctl_npt66_calcadj(npf_netmask_t len, const npf_addr_t *pref_in,
+ const npf_addr_t *pref_out)
+{
+ const uint16_t *addr6_in = (const uint16_t *)pref_in;
+ const uint16_t *addr6_out = (const uint16_t *)pref_out;
+ unsigned i, remnant, wordmask, preflen = len >> 4;
+ uint32_t adj, isum = 0, osum = 0;
+
+ /*
+ * Extract the bits within a 16-bit word (when prefix length is
+ * not dividable by 16) and include them into the sum.
+ */
+ remnant = len - (preflen << 4);
+ wordmask = (1U << remnant) - 1;
+ assert(wordmask == 0 || (len % 16) != 0);
+
+ /* Inner prefix - sum and fold. */
+ for (i = 0; i < preflen; i++) {
+ isum += addr6_in[i];
+ }
+ isum += addr6_in[i] & wordmask;
+ while (isum >> 16) {
+ isum = (isum >> 16) + (isum & 0xffff);
+ }
+
+ /* Outer prefix - sum and fold. */
+ for (i = 0; i < preflen; i++) {
+ osum += addr6_out[i];
+ }
+ osum += addr6_out[i] & wordmask;
+ while (osum >> 16) {
+ osum = (osum >> 16) + (osum & 0xffff);
+ }
+
+ /* Calculate 1's complement difference. */
+ adj = isum + ~osum;
+ while (adj >> 16) {
+ adj = (adj >> 16) + (adj & 0xffff);
+ }
+ return (uint16_t)adj;
+}
Index: src/usr.sbin/npf/npfctl/npf_parse.y
diff -u src/usr.sbin/npf/npfctl/npf_parse.y:1.31 src/usr.sbin/npf/npfctl/npf_parse.y:1.32
--- src/usr.sbin/npf/npfctl/npf_parse.y:1.31 Sat Feb 8 01:20:09 2014
+++ src/usr.sbin/npf/npfctl/npf_parse.y Thu Feb 13 03:34:40 2014
@@ -1,7 +1,7 @@
-/* $NetBSD: npf_parse.y,v 1.31 2014/02/08 01:20:09 rmind Exp $ */
+/* $NetBSD: npf_parse.y,v 1.32 2014/02/13 03:34:40 rmind Exp $ */
/*-
- * Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
+ * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -84,6 +84,7 @@ yyerror(const char *fmt, ...)
%}
%token ALG
+%token ALGO
%token ALL
%token ANY
%token APPLY
@@ -115,6 +116,7 @@ yyerror(const char *fmt, ...)
%token MAP
%token MINUS
%token NAME
+%token NPT66
%token ON
%token OUT
%token PAR_CLOSE
@@ -156,7 +158,8 @@ yyerror(const char *fmt, ...)
%type <str> proc_param_val, opt_apply, ifname, on_ifname, ifref
%type <num> port, opt_final, number, afamily, opt_family
%type <num> block_or_pass, rule_dir, group_dir, block_opts
-%type <num> opt_stateful, icmp_type, table_type, map_sd, map_type
+%type <num> opt_stateful, icmp_type, table_type
+%type <num> map_sd, map_algo, map_type
%type <var> ifaddrs, addr_or_ifaddr, port_range, icmp_type_and_code
%type <var> filt_addr, addr_and_mask, tcp_flags, tcp_flags_and_mask
%type <var> procs, proc_call, proc_param_list, proc_param
@@ -296,6 +299,11 @@ map_sd
| { $$ = NPFCTL_NAT_DYNAMIC; }
;
+map_algo
+ : ALGO NPT66 { $$ = NPF_ALGO_NPT66; }
+ | { $$ = 0; }
+ ;
+
map_type
: ARROWBOTH { $$ = NPF_NATIN | NPF_NATOUT; }
| ARROWLEFT { $$ = NPF_NATIN; }
@@ -311,13 +319,13 @@ mapseg
;
map
- : MAP ifref map_sd mapseg map_type mapseg PASS filt_opts
+ : MAP ifref map_sd map_algo mapseg map_type mapseg PASS filt_opts
{
- npfctl_build_natseg($3, $5, $2, &$4, &$6, &$8);
+ npfctl_build_natseg($3, $6, $2, &$5, &$7, &$9, $4);
}
- | MAP ifref map_sd mapseg map_type mapseg
+ | MAP ifref map_sd map_algo mapseg map_type mapseg
{
- npfctl_build_natseg($3, $5, $2, &$4, &$6, NULL);
+ npfctl_build_natseg($3, $6, $2, &$5, &$7, NULL, $4);
}
| MAP RULESET group_opts
{
Index: src/usr.sbin/npf/npfctl/npf_scan.l
diff -u src/usr.sbin/npf/npfctl/npf_scan.l:1.18 src/usr.sbin/npf/npfctl/npf_scan.l:1.19
--- src/usr.sbin/npf/npfctl/npf_scan.l:1.18 Sat Feb 8 01:20:09 2014
+++ src/usr.sbin/npf/npfctl/npf_scan.l Thu Feb 13 03:34:40 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_scan.l,v 1.18 2014/02/08 01:20:09 rmind Exp $ */
+/* $NetBSD: npf_scan.l,v 1.19 2014/02/13 03:34:40 rmind Exp $ */
/*-
* Copyright (c) 2011-2012 The NetBSD Foundation, Inc.
@@ -99,6 +99,8 @@ map return MAP;
"<->" return ARROWBOTH;
"<-" return ARROWLEFT;
"->" return ARROWRIGHT;
+algo return ALGO;
+npt66 return NPT66;
"-" return MINUS;
procedure return PROCEDURE;
\\\n yylineno++; yycolumn = 0;
Index: src/usr.sbin/npf/npftest/npftest.c
diff -u src/usr.sbin/npf/npftest/npftest.c:1.16 src/usr.sbin/npf/npftest/npftest.c:1.17
--- src/usr.sbin/npf/npftest/npftest.c:1.16 Thu Feb 6 02:51:28 2014
+++ src/usr.sbin/npf/npftest/npftest.c Thu Feb 13 03:34:40 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npftest.c,v 1.16 2014/02/06 02:51:28 rmind Exp $ */
+/* $NetBSD: npftest.c,v 1.17 2014/02/13 03:34:40 rmind Exp $ */
/*
* NPF testing framework.
@@ -255,7 +255,7 @@ main(int argc, char **argv)
rump_init();
rump_schedule();
- rumpns_npf_test_init(random);
+ rumpns_npf_test_init(inet_pton, inet_ntop, random);
if (config) {
load_npf_config(config);
Index: src/usr.sbin/npf/npftest/npftest.conf
diff -u src/usr.sbin/npf/npftest/npftest.conf:1.4 src/usr.sbin/npf/npftest/npftest.conf:1.5
--- src/usr.sbin/npf/npftest/npftest.conf:1.4 Fri Feb 7 23:45:22 2014
+++ src/usr.sbin/npf/npftest/npftest.conf Thu Feb 13 03:34:40 2014
@@ -1,4 +1,4 @@
-# $NetBSD: npftest.conf,v 1.4 2014/02/07 23:45:22 rmind Exp $
+# $NetBSD: npftest.conf,v 1.5 2014/02/13 03:34:40 rmind Exp $
$ext_if = "npftest0"
$int_if = "npftest1"
@@ -19,15 +19,23 @@ $local_ip4 = 10.1.1.4
$local_net = { 10.1.1.0/24 }
$ports = { 8000, 9000 }
+$net6_inner = fd01:203:405::/48
+$net6_outer = 2001:db8:1::/48
+
map $ext_if static $local_ip3 <-> $pub_ip3
map $ext_if dynamic $local_ip2 <-> $pub_ip2
map $ext_if dynamic $local_net -> $pub_ip1
map $ext_if dynamic $local_ip1 port 6000 <- $pub_ip1 port 8000
+map $ext_if static algo npt66 $net6_inner <-> $net6_outer
+
group "ext" on $ext_if {
pass out final from $local_ip3
pass in final to $pub_ip3
+ pass out final from $net6_inner
+ pass in final to $net6_outer
+
pass stateful out final proto tcp flags S/SA all
pass stateful out final from $local_net
pass stateful in final to any port $ports
Index: src/usr.sbin/npf/npftest/npftest.h
diff -u src/usr.sbin/npf/npftest/npftest.h:1.12 src/usr.sbin/npf/npftest/npftest.h:1.13
--- src/usr.sbin/npf/npftest/npftest.h:1.12 Thu Feb 6 02:51:28 2014
+++ src/usr.sbin/npf/npftest/npftest.h Thu Feb 13 03:34:40 2014
@@ -12,7 +12,9 @@
#include <net/if.h>
-void rumpns_npf_test_init(long (*)(void));
+void rumpns_npf_test_init(int (*)(int, const char *, void *),
+ const char *(*)(int, const void *, char *, socklen_t),
+ long (*)(void));
int rumpns_npf_test_load(const void *);
ifnet_t * rumpns_npf_test_addif(const char *, bool, bool);
ifnet_t * rumpns_npf_test_getif(const char *);
Index: src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c:1.4 src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c:1.5
--- src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c:1.4 Mon Dec 24 19:05:47 2012
+++ src/usr.sbin/npf/npftest/libnpftest/npf_mbuf_subr.c Thu Feb 13 03:34:40 2014
@@ -136,6 +136,15 @@ mbuf_return_hdrs(struct mbuf *m, bool et
return (void *)(iphdr + 1);
}
+void *
+mbuf_return_hdrs6(struct mbuf *m, struct ip6_hdr **ip6)
+{
+ struct ip6_hdr *ip6hdr = mtod(m, struct ip6_hdr *);
+
+ *ip6 = ip6hdr;
+ return (void *)(ip6hdr + 1);
+}
+
void
mbuf_icmp_append(struct mbuf *m, struct mbuf *m_orig)
{
Index: src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c:1.7 src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c:1.8
--- src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c:1.7 Fri Feb 7 23:45:22 2014
+++ src/usr.sbin/npf/npftest/libnpftest/npf_nat_test.c Thu Feb 13 03:34:40 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_nat_test.c,v 1.7 2014/02/07 23:45:22 rmind Exp $ */
+/* $NetBSD: npf_nat_test.c,v 1.8 2014/02/13 03:34:40 rmind Exp $ */
/*
* NPF NAT test.
@@ -27,6 +27,7 @@ static const struct test_case {
const char * ifname;
int di;
int ret;
+ int af;
const char * taddr;
in_port_t tport;
} test_cases[] = {
@@ -38,32 +39,32 @@ static const struct test_case {
{
LOCAL_IP1, 15000, REMOTE_IP1, 7000,
NPF_NATOUT, IFNAME_EXT, PFIL_OUT,
- RESULT_PASS, PUB_IP1, RANDOM_PORT
+ RESULT_PASS, AF_INET, PUB_IP1, RANDOM_PORT
},
{
LOCAL_IP1, 15000, REMOTE_IP1, 7000,
NPF_NATOUT, IFNAME_EXT, PFIL_OUT,
- RESULT_PASS, PUB_IP1, RANDOM_PORT
+ RESULT_PASS, AF_INET, PUB_IP1, RANDOM_PORT
},
{
LOCAL_IP1, 15000, REMOTE_IP1, 7000,
NPF_NATOUT, IFNAME_EXT, PFIL_IN,
- RESULT_BLOCK, NULL, 0
+ RESULT_BLOCK, AF_INET, NULL, 0
},
{
REMOTE_IP1, 7000, LOCAL_IP1, 15000,
NPF_NATOUT, IFNAME_EXT, PFIL_IN,
- RESULT_BLOCK, NULL, 0
+ RESULT_BLOCK, AF_INET, NULL, 0
},
{
REMOTE_IP1, 7000, PUB_IP1, RANDOM_PORT,
NPF_NATOUT, IFNAME_INT, PFIL_IN,
- RESULT_BLOCK, NULL, 0
+ RESULT_BLOCK, AF_INET, NULL, 0
},
{
REMOTE_IP1, 7000, PUB_IP1, RANDOM_PORT,
NPF_NATOUT, IFNAME_EXT, PFIL_IN,
- RESULT_PASS, LOCAL_IP1, 15000
+ RESULT_PASS, AF_INET, LOCAL_IP1, 15000
},
/*
@@ -73,12 +74,12 @@ static const struct test_case {
{
REMOTE_IP2, 16000, PUB_IP1, 8000,
NPF_NATIN, IFNAME_EXT, PFIL_IN,
- RESULT_PASS, LOCAL_IP1, 6000
+ RESULT_PASS, AF_INET, LOCAL_IP1, 6000
},
{
LOCAL_IP1, 6000, REMOTE_IP2, 16000,
NPF_NATIN, IFNAME_EXT, PFIL_OUT,
- RESULT_PASS, PUB_IP1, 8000
+ RESULT_PASS, AF_INET, PUB_IP1, 8000
},
/*
@@ -88,22 +89,22 @@ static const struct test_case {
{
REMOTE_IP2, 17000, PUB_IP2, 9000,
NPF_BINAT, IFNAME_EXT, PFIL_IN,
- RESULT_PASS, LOCAL_IP2, 9000
+ RESULT_PASS, AF_INET, LOCAL_IP2, 9000
},
{
LOCAL_IP2, 9000, REMOTE_IP2, 17000,
NPF_BINAT, IFNAME_EXT, PFIL_OUT,
- RESULT_PASS, PUB_IP2, 9000
+ RESULT_PASS, AF_INET, PUB_IP2, 9000
},
{
LOCAL_IP2, 18000, REMOTE_IP2, 9000,
NPF_BINAT, IFNAME_EXT, PFIL_OUT,
- RESULT_PASS, PUB_IP2, 18000
+ RESULT_PASS, AF_INET, PUB_IP2, 18000
},
{
REMOTE_IP2, 9000, PUB_IP2, 18000,
NPF_BINAT, IFNAME_EXT, PFIL_IN,
- RESULT_PASS, LOCAL_IP2, 18000
+ RESULT_PASS, AF_INET, LOCAL_IP2, 18000
},
/*
@@ -113,21 +114,40 @@ static const struct test_case {
{
LOCAL_IP3, 19000, REMOTE_IP3, 10000,
NPF_BINAT, IFNAME_EXT, PFIL_OUT,
- RESULT_PASS, PUB_IP3, 19000
+ RESULT_PASS, AF_INET, PUB_IP3, 19000
},
{
REMOTE_IP3, 10000, PUB_IP3, 19000,
NPF_BINAT, IFNAME_EXT, PFIL_IN,
- RESULT_PASS, LOCAL_IP3, 19000
+ RESULT_PASS, AF_INET, LOCAL_IP3, 19000
+ },
+
+ /*
+ * NPTv6 case:
+ * map $ext_if static algo npt66 $net6_inner <-> $net6_outer
+ */
+ {
+ LOCAL_IP6, 1000, REMOTE_IP6, 1001,
+ NPF_BINAT, IFNAME_EXT, PFIL_OUT,
+ RESULT_PASS, AF_INET6, EXPECTED_IP6, 1000
+ },
+ {
+ REMOTE_IP6, 1001, EXPECTED_IP6, 1000,
+ NPF_BINAT, IFNAME_EXT, PFIL_IN,
+ RESULT_PASS, AF_INET6, LOCAL_IP6, 1000
},
};
static bool
-nmatch_addr(const char *saddr, const struct in_addr *addr2)
+nmatch_addr(int af, const char *saddr, const npf_addr_t *addr2)
{
- const in_addr_t addr1 = inet_addr(saddr);
- return memcmp(&addr1, &addr2->s_addr, sizeof(in_addr_t)) != 0;
+ npf_addr_t addr1;
+ size_t len;
+
+ npf_inet_pton(af, saddr, &addr1);
+ len = af == AF_INET ? sizeof(struct in_addr) : sizeof(struct in6_addr);
+ return memcmp(&addr1, addr2, len) != 0;
}
static bool
@@ -135,6 +155,7 @@ checkresult(bool verbose, unsigned i, st
{
const struct test_case *t = &test_cases[i];
npf_cache_t npc = { .npc_info = 0 };
+ const int af = t->af;
nbuf_t nbuf;
if (verbose) {
@@ -150,14 +171,17 @@ checkresult(bool verbose, unsigned i, st
return false;
}
- const struct ip *ip = npc.npc_ip.v4;
const struct udphdr *uh = npc.npc_l4.udp;
if (verbose) {
- printf("\tpost-translation: src %s (%d)",
- inet_ntoa(ip->ip_src), ntohs(uh->uh_sport));
- printf(" dst %s (%d)\n",
- inet_ntoa(ip->ip_dst), ntohs(uh->uh_dport));
+ char sbuf[64], dbuf[64];
+
+ npf_inet_ntop(af, npc.npc_ips[NPF_SRC], sbuf, sizeof(sbuf));
+ npf_inet_ntop(af, npc.npc_ips[NPF_DST], dbuf, sizeof(dbuf));
+
+ printf("\tpost-translation:");
+ printf("src %s (%d) ", sbuf, ntohs(uh->uh_sport));
+ printf("dst %s (%d)\n", dbuf, ntohs(uh->uh_dport));
}
if (error != t->ret) {
return false;
@@ -170,10 +194,11 @@ checkresult(bool verbose, unsigned i, st
in_addr_t dport = forw ? t->dport : t->tport;
bool defect = false;
- defect |= nmatch_addr(saddr, &ip->ip_src);
+ defect |= nmatch_addr(af, saddr, npc.npc_ips[NPF_SRC]);
defect |= sport != ntohs(uh->uh_sport);
- defect |= nmatch_addr(daddr, &ip->ip_dst);
+ defect |= nmatch_addr(af, daddr, npc.npc_ips[NPF_DST]);
defect |= dport != ntohs(uh->uh_dport);
+
return !defect;
}
@@ -181,13 +206,25 @@ static struct mbuf *
fill_packet(const struct test_case *t)
{
struct mbuf *m;
- struct ip *ip;
+ void *ipsrc, *ipdst;
struct udphdr *uh;
- m = mbuf_construct(IPPROTO_UDP);
- uh = mbuf_return_hdrs(m, false, &ip);
- ip->ip_src.s_addr = inet_addr(t->src);
- ip->ip_dst.s_addr = inet_addr(t->dst);
+ if (t->af == AF_INET6) {
+ struct ip6_hdr *ip6;
+
+ m = mbuf_construct6(IPPROTO_UDP);
+ uh = mbuf_return_hdrs6(m, &ip6);
+ ipsrc = &ip6->ip6_src, ipdst = &ip6->ip6_dst;
+ } else {
+ struct ip *ip;
+
+ m = mbuf_construct(IPPROTO_UDP);
+ uh = mbuf_return_hdrs(m, false, &ip);
+ ipsrc = &ip->ip_src.s_addr, ipdst = &ip->ip_dst.s_addr;
+ }
+
+ npf_inet_pton(t->af, t->src, ipsrc);
+ npf_inet_pton(t->af, t->dst, ipdst);
uh->uh_sport = htons(t->sport);
uh->uh_dport = htons(t->dport);
return m;
Index: src/usr.sbin/npf/npftest/libnpftest/npf_test.h
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.14 src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.15
--- src/usr.sbin/npf/npftest/libnpftest/npf_test.h:1.14 Fri Feb 7 23:45:22 2014
+++ src/usr.sbin/npf/npftest/libnpftest/npf_test.h Thu Feb 13 03:34:40 2014
@@ -42,7 +42,13 @@
#define REMOTE_IP2 "192.0.2.102"
#define REMOTE_IP3 "192.0.2.103"
-void npf_test_init(long (*)(void));
+#define LOCAL_IP6 "fd01:203:405:1::1234"
+#define REMOTE_IP6 "2001:db8:fefe::1010"
+#define EXPECTED_IP6 "2001:db8:1:d550::1234"
+
+void npf_test_init(int (*)(int, const char *, void *),
+ const char *(*)(int, const void *, char *, socklen_t),
+ long (*)(void));
int npf_test_load(const void *);
ifnet_t * npf_test_addif(const char *, bool, bool);
ifnet_t * npf_test_getif(const char *);
@@ -56,6 +62,7 @@ struct mbuf * mbuf_construct_ether(int);
struct mbuf * mbuf_construct(int);
struct mbuf * mbuf_construct6(int);
void * mbuf_return_hdrs(struct mbuf *, bool, struct ip **);
+void * mbuf_return_hdrs6(struct mbuf *, struct ip6_hdr **);
void mbuf_icmp_append(struct mbuf *, struct mbuf *);
bool npf_nbuf_test(bool);
@@ -66,4 +73,7 @@ bool npf_state_test(bool);
bool npf_rule_test(bool);
bool npf_nat_test(bool);
+int npf_inet_pton(int, const char *, void *);
+const char * npf_inet_ntop(int, const void *, char *, socklen_t);
+
#endif
Index: src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c
diff -u src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c:1.8 src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c:1.9
--- src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c:1.8 Wed Feb 5 03:49:48 2014
+++ src/usr.sbin/npf/npftest/libnpftest/npf_test_subr.c Thu Feb 13 03:34:40 2014
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_test_subr.c,v 1.8 2014/02/05 03:49:48 rmind Exp $ */
+/* $NetBSD: npf_test_subr.c,v 1.9 2014/02/13 03:34:40 rmind Exp $ */
/*
* NPF initialisation and handler routines.
@@ -19,14 +19,21 @@ static npf_state_t cstream_state;
static void * cstream_ptr;
static bool cstream_retval;
+static long (*_random_func)(void);
+static int (*_pton_func)(int, const char *, void *);
+static const char * (*_ntop_func)(int, const void *, char *, socklen_t);
+
static void npf_state_sample(npf_state_t *, bool);
-static long (*npf_random_func)(void) = NULL;
void
-npf_test_init(long (*rndfunc)(void))
+npf_test_init(int (*pton_func)(int, const char *, void *),
+ const char *(*ntop_func)(int, const void *, char *, socklen_t),
+ long (*rndfunc)(void))
{
npf_state_setsampler(npf_state_sample);
- npf_random_func = rndfunc;
+ _pton_func = pton_func;
+ _ntop_func = ntop_func;
+ _random_func = rndfunc;
}
int
@@ -118,11 +125,23 @@ npf_test_statetrack(const void *data, si
return 0;
}
+int
+npf_inet_pton(int af, const char *src, void *dst)
+{
+ return _pton_func(af, src, dst);
+}
+
+const char *
+npf_inet_ntop(int af, const void *src, char *dst, socklen_t size)
+{
+ return _ntop_func(af, src, dst, size);
+}
+
/*
* Need to override for cprng_fast32() -- we need deterministic PRNG.
*/
uint32_t
_arc4random(void)
{
- return (uint32_t)(npf_random_func ? npf_random_func() : random());
+ return (uint32_t)(_random_func ? _random_func() : random());
}