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()); }