diff options
| author | rmind <rmind@NetBSD.org> | 2014-02-19 03:51:31 +0000 |
|---|---|---|
| committer | rmind <rmind@NetBSD.org> | 2014-02-19 03:51:31 +0000 |
| commit | 8c1933dfc56bbb786d3aa59b8029dc0cefd932d7 (patch) | |
| tree | 4ba8e4fc5a5213dfae8c8d167dbc02f8cdb275a3 /sys | |
| parent | 4db72dd4b3ecdb9b9c6bf93c96c35b37727fecc6 (diff) | |
NPF: fix the recent breakage of the traceroute ALG. Also, simplify and
refactor a little bit.
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/net/npf/npf_alg_icmp.c | 37 | ||||
| -rw-r--r-- | sys/net/npf/npf_impl.h | 5 | ||||
| -rw-r--r-- | sys/net/npf/npf_inet.c | 50 | ||||
| -rw-r--r-- | sys/net/npf/npf_nat.c | 63 |
4 files changed, 82 insertions, 73 deletions
diff --git a/sys/net/npf/npf_alg_icmp.c b/sys/net/npf/npf_alg_icmp.c index 664b99a5d70..6aaa3efd043 100644 --- a/sys/net/npf/npf_alg_icmp.c +++ b/sys/net/npf/npf_alg_icmp.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_alg_icmp.c,v 1.19 2014/02/16 22:10:40 rmind Exp $ */ +/* $NetBSD: npf_alg_icmp.c,v 1.20 2014/02/19 03:51:31 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.19 2014/02/16 22:10:40 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.20 2014/02/19 03:51:31 rmind Exp $"); #include <sys/param.h> #include <sys/module.h> @@ -305,6 +305,7 @@ npfa_icmp_session(npf_cache_t *npc, nbuf_t *nbuf, int di) static bool npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) { + const u_int which = NPF_SRC; npf_cache_t enpc; if (forw || !npf_iscached(npc, NPC_ICMP)) @@ -315,6 +316,9 @@ npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) KASSERT(npf_iscached(&enpc, NPC_IP46)); KASSERT(npf_iscached(&enpc, NPC_LAYER4)); + /* + * ICMP: fetch the current checksum we are going to fixup. + */ struct icmp *ic = npc->npc_l4.icmp; uint16_t cksum = ic->icmp_cksum; @@ -322,12 +326,9 @@ npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) offsetof(struct icmp6_hdr, icmp6_cksum)); /* - * 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. + * Fetch the IP and port in the _embedded_ packet. Also, fetch + * the IPv4 and TCP/UDP checksums before they are rewritten. + * Calculate the part of the ICMP checksum fixup. */ const int proto = enpc.npc_proto; uint16_t ipcksum = 0, l4cksum = 0; @@ -340,7 +341,7 @@ npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) const struct ip *eip = enpc.npc_ip.v4; ipcksum = eip->ip_sum; } - cksum = npf_addr_cksum(cksum, enpc.npc_alen, enpc.npc_ips[NPF_SRC], addr); + cksum = npf_addr_cksum(cksum, enpc.npc_alen, enpc.npc_ips[which], addr); switch (proto) { case IPPROTO_TCP: { @@ -363,17 +364,23 @@ npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) } /* - * Rewrite the source IP address and port of the embedded IP header, - * which represents the original packet. This updates the checksums - * in the embedded packet. + * Translate the embedded packet. The following changes will + * be performed by npf_napt_rwr(): + * + * 1) Rewrite the IP address and, if not ICMP, port. + * 2) Rewrite the TCP/UDP checksum (if not ICMP). + * 3) Rewrite the IPv4 checksum for (1) and (2). + * + * XXX: Assumes NPF_NATOUT (source address/port). Currently, + * npfa_icmp_match() matches only for the PFIL_OUT traffic. */ - if (npf_nat_translate(&enpc, nbuf, nt, forw)) { + if (npf_napt_rwr(&enpc, which, addr, port)) { return false; } /* - * Finish calculation of the ICMP checksum: include the checksum - * change in the embedded packet. + * Finally, finish the ICMP checksum fixup: include the checksum + * changes in the embedded packet. */ if (npf_iscached(&enpc, NPC_IP4)) { const struct ip *eip = enpc.npc_ip.v4; diff --git a/sys/net/npf/npf_impl.h b/sys/net/npf/npf_impl.h index 1f8493d5ba5..b242e23ec92 100644 --- a/sys/net/npf/npf_impl.h +++ b/sys/net/npf/npf_impl.h @@ -1,4 +1,4 @@ -/* $NetBSD: npf_impl.h,v 1.48 2014/02/16 22:10:40 rmind Exp $ */ +/* $NetBSD: npf_impl.h,v 1.49 2014/02/19 03:51:31 rmind Exp $ */ /*- * Copyright (c) 2009-2014 The NetBSD Foundation, Inc. @@ -200,6 +200,8 @@ 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); +int npf_napt_rwr(const npf_cache_t *, u_int, const npf_addr_t *, + const in_addr_t); int npf_npt66_rwr(const npf_cache_t *, u_int, const npf_addr_t *, npf_netmask_t, uint16_t); @@ -341,7 +343,6 @@ bool npf_nat_sharepm(npf_natpolicy_t *, 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 *, 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 *); diff --git a/sys/net/npf/npf_inet.c b/sys/net/npf/npf_inet.c index 69c67d9109d..38fafcf095b 100644 --- a/sys/net/npf/npf_inet.c +++ b/sys/net/npf/npf_inet.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_inet.c,v 1.29 2014/02/13 03:34:40 rmind Exp $ */ +/* $NetBSD: npf_inet.c,v 1.30 2014/02/19 03:51:31 rmind Exp $ */ /*- * Copyright (c) 2009-2014 The NetBSD Foundation, Inc. @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.29 2014/02/13 03:34:40 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.30 2014/02/19 03:51:31 rmind Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -578,7 +578,7 @@ npf_rwrcksum(const npf_cache_t *npc, u_int which, } /* Nothing else to do for ICMP. */ - if (proto == IPPROTO_ICMP) { + if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) { return true; } KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP)); @@ -617,6 +617,50 @@ npf_rwrcksum(const npf_cache_t *npc, u_int which, } /* + * npf_napt_rwr: perform address and/or port translation. + */ +int +npf_napt_rwr(const npf_cache_t *npc, u_int which, + const npf_addr_t *addr, const in_addr_t port) +{ + const unsigned proto = npc->npc_proto; + + /* + * 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, which, addr, port)) { + return EINVAL; + } + if (!npf_rwrip(npc, which, addr)) { + return EINVAL; + } + if (port == 0) { + /* Done. */ + return 0; + } + + switch (proto) { + case IPPROTO_TCP: + case IPPROTO_UDP: + /* Rewrite source/destination port. */ + if (!npf_rwrport(npc, which, port)) { + return EINVAL; + } + break; + case IPPROTO_ICMP: + case IPPROTO_ICMPV6: + KASSERT(npf_iscached(npc, NPC_ICMP)); + /* Nothing. */ + break; + default: + return ENOTSUP; + } + return 0; +} + +/* * IPv6-to-IPv6 Network Prefix Translation (NPTv6), as per RFC 6296. */ diff --git a/sys/net/npf/npf_nat.c b/sys/net/npf/npf_nat.c index a720efe627a..ffb6827c62e 100644 --- a/sys/net/npf/npf_nat.c +++ b/sys/net/npf/npf_nat.c @@ -1,4 +1,4 @@ -/* $NetBSD: npf_nat.c,v 1.25 2014/02/13 03:34:40 rmind Exp $ */ +/* $NetBSD: npf_nat.c,v 1.26 2014/02/19 03:51:31 rmind Exp $ */ /*- * Copyright (c) 2014 Mindaugas Rasiukevicius <rmind at netbsd org> @@ -71,7 +71,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.25 2014/02/13 03:34:40 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.26 2014/02/19 03:51:31 rmind Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -549,62 +549,18 @@ out: } /* - * npf_nat_rwr: perform address and/or port translation. - */ -static int -npf_nat_rwr(npf_cache_t *npc, const npf_natpolicy_t *np, - const npf_addr_t *addr, const in_addr_t port, bool forw) -{ - const unsigned proto = npc->npc_proto; - const u_int which = npf_nat_which(np->n_type, forw); - - /* - * 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, which, addr, port)) { - return EINVAL; - } - if (!npf_rwrip(npc, which, addr)) { - return EINVAL; - } - if ((np->n_flags & NPF_NAT_PORTS) == 0) { - /* Done. */ - return 0; - } - - switch (proto) { - case IPPROTO_TCP: - case IPPROTO_UDP: - /* Rewrite source/destination port. */ - if (!npf_rwrport(npc, which, port)) { - return EINVAL; - } - break; - case IPPROTO_ICMP: - KASSERT(npf_iscached(npc, NPC_ICMP)); - /* Nothing. */ - break; - default: - return ENOTSUP; - } - return 0; -} - -/* * npf_nat_translate: perform translation given the state data. */ -int +static inline int npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) { 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. */ @@ -617,14 +573,16 @@ npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) } KASSERT((np->n_flags & NPF_NAT_PORTS) != 0 || port == 0); - /* Execute ALG hook first. */ + /* Execute ALG translation first. */ if ((npc->npc_info & NPC_ALG_EXEC) == 0) { npc->npc_info |= NPC_ALG_EXEC; npf_alg_exec(npc, nbuf, nt, forw); + npf_recache(npc, nbuf); } + KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)); /* Finally, perform the translation. */ - return npf_nat_rwr(npc, np, addr, port, forw); + return npf_napt_rwr(npc, which, addr, port); } /* @@ -633,17 +591,16 @@ npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) static inline int npf_nat_algo(npf_cache_t *npc, const npf_natpolicy_t *np, bool forw) { - u_int which; + const u_int which = npf_nat_which(np->n_type, forw); 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); + error = npf_napt_rwr(npc, which, &np->n_taddr, np->n_tport); break; } |
