Wed Feb 19 03:51:31 2014 UTC ()
NPF: fix the recent breakage of the traceroute ALG.  Also, simplify and
refactor a little bit.


(rmind)
diff -r1.19 -r1.20 src/sys/net/npf/npf_alg_icmp.c
diff -r1.48 -r1.49 src/sys/net/npf/npf_impl.h
diff -r1.29 -r1.30 src/sys/net/npf/npf_inet.c
diff -r1.25 -r1.26 src/sys/net/npf/npf_nat.c

cvs diff -r1.19 -r1.20 src/sys/net/npf/npf_alg_icmp.c (expand / switch to unified diff)

--- src/sys/net/npf/npf_alg_icmp.c 2014/02/16 22:10:40 1.19
+++ src/sys/net/npf/npf_alg_icmp.c 2014/02/19 03:51:31 1.20
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: npf_alg_icmp.c,v 1.19 2014/02/16 22:10:40 rmind Exp $ */ 1/* $NetBSD: npf_alg_icmp.c,v 1.20 2014/02/19 03:51:31 rmind Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2010 The NetBSD Foundation, Inc. 4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This material is based upon work partially supported by The 7 * This material is based upon work partially supported by The
8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. 8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -24,27 +24,27 @@ @@ -24,27 +24,27 @@
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * NPF ALG for ICMP and traceroute translations. 33 * NPF ALG for ICMP and traceroute translations.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.19 2014/02/16 22:10:40 rmind Exp $"); 37__KERNEL_RCSID(0, "$NetBSD: npf_alg_icmp.c,v 1.20 2014/02/19 03:51:31 rmind Exp $");
38 38
39#include <sys/param.h> 39#include <sys/param.h>
40#include <sys/module.h> 40#include <sys/module.h>
41 41
42#include <netinet/in_systm.h> 42#include <netinet/in_systm.h>
43#include <netinet/in.h> 43#include <netinet/in.h>
44#include <netinet/ip.h> 44#include <netinet/ip.h>
45#include <netinet/tcp.h> 45#include <netinet/tcp.h>
46#include <netinet/udp.h> 46#include <netinet/udp.h>
47#include <netinet/ip_icmp.h> 47#include <netinet/ip_icmp.h>
48#include <netinet/icmp6.h> 48#include <netinet/icmp6.h>
49#include <net/pfil.h> 49#include <net/pfil.h>
50 50
@@ -295,95 +295,102 @@ npfa_icmp_session(npf_cache_t *npc, nbuf @@ -295,95 +295,102 @@ npfa_icmp_session(npf_cache_t *npc, nbuf
295 } 295 }
296 296
297 /* Lookup for a session using embedded packet. */ 297 /* Lookup for a session using embedded packet. */
298 return npf_session_lookup(&enpc, nbuf, di, &forw); 298 return npf_session_lookup(&enpc, nbuf, di, &forw);
299} 299}
300 300
301/* 301/*
302 * npfa_icmp_nat: ALG translator - rewrites IP address in the IP header 302 * npfa_icmp_nat: ALG translator - rewrites IP address in the IP header
303 * which is embedded in ICMP packet. Note: backwards stream only. 303 * which is embedded in ICMP packet. Note: backwards stream only.
304 */ 304 */
305static bool 305static bool
306npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) 306npfa_icmp_nat(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw)
307{ 307{
 308 const u_int which = NPF_SRC;
308 npf_cache_t enpc; 309 npf_cache_t enpc;
309 310
310 if (forw || !npf_iscached(npc, NPC_ICMP)) 311 if (forw || !npf_iscached(npc, NPC_ICMP))
311 return false; 312 return false;
312 if (!npfa_icmp_inspect(npc, nbuf, &enpc)) 313 if (!npfa_icmp_inspect(npc, nbuf, &enpc))
313 return false; 314 return false;
314 315
315 KASSERT(npf_iscached(&enpc, NPC_IP46)); 316 KASSERT(npf_iscached(&enpc, NPC_IP46));
316 KASSERT(npf_iscached(&enpc, NPC_LAYER4)); 317 KASSERT(npf_iscached(&enpc, NPC_LAYER4));
317 318
 319 /*
 320 * ICMP: fetch the current checksum we are going to fixup.
 321 */
318 struct icmp *ic = npc->npc_l4.icmp; 322 struct icmp *ic = npc->npc_l4.icmp;
319 uint16_t cksum = ic->icmp_cksum; 323 uint16_t cksum = ic->icmp_cksum;
320 324
321 CTASSERT(offsetof(struct icmp, icmp_cksum) == 325 CTASSERT(offsetof(struct icmp, icmp_cksum) ==
322 offsetof(struct icmp6_hdr, icmp6_cksum)); 326 offsetof(struct icmp6_hdr, icmp6_cksum));
323 327
324 /* 328 /*
325 * Retrieve the original address and port, then calculate ICMP 329 * Fetch the IP and port in the _embedded_ packet. Also, fetch
326 * checksum for these changes in the embedded packet. While data 330 * the IPv4 and TCP/UDP checksums before they are rewritten.
327 * is not rewritten in the cache, save IP and TCP/UDP checksums. 331 * Calculate the part of the ICMP checksum fixup.
328 * 
329 * XXX: Assumes NPF_NATOUT (source address/port). Currently, 
330 * npfa_icmp_match() matches only for the PFIL_OUT traffic. 
331 */ 332 */
332 const int proto = enpc.npc_proto; 333 const int proto = enpc.npc_proto;
333 uint16_t ipcksum = 0, l4cksum = 0; 334 uint16_t ipcksum = 0, l4cksum = 0;
334 npf_addr_t *addr; 335 npf_addr_t *addr;
335 in_port_t port; 336 in_port_t port;
336 337
337 npf_nat_getorig(nt, &addr, &port); 338 npf_nat_getorig(nt, &addr, &port);
338 339
339 if (npf_iscached(&enpc, NPC_IP4)) { 340 if (npf_iscached(&enpc, NPC_IP4)) {
340 const struct ip *eip = enpc.npc_ip.v4; 341 const struct ip *eip = enpc.npc_ip.v4;
341 ipcksum = eip->ip_sum; 342 ipcksum = eip->ip_sum;
342 } 343 }
343 cksum = npf_addr_cksum(cksum, enpc.npc_alen, enpc.npc_ips[NPF_SRC], addr); 344 cksum = npf_addr_cksum(cksum, enpc.npc_alen, enpc.npc_ips[which], addr);
344 345
345 switch (proto) { 346 switch (proto) {
346 case IPPROTO_TCP: { 347 case IPPROTO_TCP: {
347 const struct tcphdr *th = enpc.npc_l4.tcp; 348 const struct tcphdr *th = enpc.npc_l4.tcp;
348 cksum = npf_fixup16_cksum(cksum, th->th_sport, port); 349 cksum = npf_fixup16_cksum(cksum, th->th_sport, port);
349 l4cksum = th->th_sum; 350 l4cksum = th->th_sum;
350 break; 351 break;
351 } 352 }
352 case IPPROTO_UDP: { 353 case IPPROTO_UDP: {
353 const struct udphdr *uh = enpc.npc_l4.udp; 354 const struct udphdr *uh = enpc.npc_l4.udp;
354 cksum = npf_fixup16_cksum(cksum, uh->uh_sport, port); 355 cksum = npf_fixup16_cksum(cksum, uh->uh_sport, port);
355 l4cksum = uh->uh_sum; 356 l4cksum = uh->uh_sum;
356 break; 357 break;
357 } 358 }
358 case IPPROTO_ICMP: 359 case IPPROTO_ICMP:
359 case IPPROTO_ICMPV6: 360 case IPPROTO_ICMPV6:
360 break; 361 break;
361 default: 362 default:
362 return false; 363 return false;
363 } 364 }
364 365
365 /* 366 /*
366 * Rewrite the source IP address and port of the embedded IP header, 367 * Translate the embedded packet. The following changes will
367 * which represents the original packet. This updates the checksums 368 * be performed by npf_napt_rwr():
368 * in the embedded packet. 369 *
 370 * 1) Rewrite the IP address and, if not ICMP, port.
 371 * 2) Rewrite the TCP/UDP checksum (if not ICMP).
 372 * 3) Rewrite the IPv4 checksum for (1) and (2).
 373 *
 374 * XXX: Assumes NPF_NATOUT (source address/port). Currently,
 375 * npfa_icmp_match() matches only for the PFIL_OUT traffic.
369 */ 376 */
370 if (npf_nat_translate(&enpc, nbuf, nt, forw)) { 377 if (npf_napt_rwr(&enpc, which, addr, port)) {
371 return false; 378 return false;
372 } 379 }
373 380
374 /* 381 /*
375 * Finish calculation of the ICMP checksum: include the checksum 382 * Finally, finish the ICMP checksum fixup: include the checksum
376 * change in the embedded packet. 383 * changes in the embedded packet.
377 */ 384 */
378 if (npf_iscached(&enpc, NPC_IP4)) { 385 if (npf_iscached(&enpc, NPC_IP4)) {
379 const struct ip *eip = enpc.npc_ip.v4; 386 const struct ip *eip = enpc.npc_ip.v4;
380 cksum = npf_fixup16_cksum(cksum, ipcksum, eip->ip_sum); 387 cksum = npf_fixup16_cksum(cksum, ipcksum, eip->ip_sum);
381 } 388 }
382 switch (proto) { 389 switch (proto) {
383 case IPPROTO_TCP: { 390 case IPPROTO_TCP: {
384 const struct tcphdr *th = enpc.npc_l4.tcp; 391 const struct tcphdr *th = enpc.npc_l4.tcp;
385 cksum = npf_fixup16_cksum(cksum, l4cksum, th->th_sum); 392 cksum = npf_fixup16_cksum(cksum, l4cksum, th->th_sum);
386 break; 393 break;
387 } 394 }
388 case IPPROTO_UDP: 395 case IPPROTO_UDP:
389 if (l4cksum) { 396 if (l4cksum) {

cvs diff -r1.48 -r1.49 src/sys/net/npf/npf_impl.h (expand / switch to unified diff)

--- src/sys/net/npf/npf_impl.h 2014/02/16 22:10:40 1.48
+++ src/sys/net/npf/npf_impl.h 2014/02/19 03:51:31 1.49
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: npf_impl.h,v 1.48 2014/02/16 22:10:40 rmind Exp $ */ 1/* $NetBSD: npf_impl.h,v 1.49 2014/02/19 03:51:31 rmind Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2009-2014 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This material is based upon work partially supported by The 7 * This material is based upon work partially supported by The
8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. 8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -190,26 +190,28 @@ u_int npf_ifmap_id(const ifnet_t *); @@ -190,26 +190,28 @@ u_int npf_ifmap_id(const ifnet_t *);
190int npf_pfil_register(bool); 190int npf_pfil_register(bool);
191void npf_pfil_unregister(bool); 191void npf_pfil_unregister(bool);
192bool npf_pfil_registered_p(void); 192bool npf_pfil_registered_p(void);
193int npf_packet_handler(void *, struct mbuf **, ifnet_t *, int); 193int npf_packet_handler(void *, struct mbuf **, ifnet_t *, int);
194 194
195/* Protocol helpers. */ 195/* Protocol helpers. */
196int npf_cache_all(npf_cache_t *, nbuf_t *); 196int npf_cache_all(npf_cache_t *, nbuf_t *);
197void npf_recache(npf_cache_t *, nbuf_t *); 197void npf_recache(npf_cache_t *, nbuf_t *);
198 198
199bool npf_rwrip(const npf_cache_t *, u_int, const npf_addr_t *); 199bool npf_rwrip(const npf_cache_t *, u_int, const npf_addr_t *);
200bool npf_rwrport(const npf_cache_t *, u_int, const in_port_t); 200bool npf_rwrport(const npf_cache_t *, u_int, const in_port_t);
201bool npf_rwrcksum(const npf_cache_t *, u_int, 201bool npf_rwrcksum(const npf_cache_t *, u_int,
202 const npf_addr_t *, const in_port_t); 202 const npf_addr_t *, const in_port_t);
 203int npf_napt_rwr(const npf_cache_t *, u_int, const npf_addr_t *,
 204 const in_addr_t);
203int npf_npt66_rwr(const npf_cache_t *, u_int, const npf_addr_t *, 205int npf_npt66_rwr(const npf_cache_t *, u_int, const npf_addr_t *,
204 npf_netmask_t, uint16_t); 206 npf_netmask_t, uint16_t);
205 207
206uint16_t npf_fixup16_cksum(uint16_t, uint16_t, uint16_t); 208uint16_t npf_fixup16_cksum(uint16_t, uint16_t, uint16_t);
207uint16_t npf_fixup32_cksum(uint16_t, uint32_t, uint32_t); 209uint16_t npf_fixup32_cksum(uint16_t, uint32_t, uint32_t);
208uint16_t npf_addr_cksum(uint16_t, int, const npf_addr_t *, 210uint16_t npf_addr_cksum(uint16_t, int, const npf_addr_t *,
209 const npf_addr_t *); 211 const npf_addr_t *);
210uint32_t npf_addr_mix(const int, const npf_addr_t *, const npf_addr_t *); 212uint32_t npf_addr_mix(const int, const npf_addr_t *, const npf_addr_t *);
211int npf_addr_cmp(const npf_addr_t *, const npf_netmask_t, 213int npf_addr_cmp(const npf_addr_t *, const npf_netmask_t,
212 const npf_addr_t *, const npf_netmask_t, const int); 214 const npf_addr_t *, const npf_netmask_t, const int);
213void npf_addr_mask(const npf_addr_t *, const npf_netmask_t, 215void npf_addr_mask(const npf_addr_t *, const npf_netmask_t,
214 const int, npf_addr_t *); 216 const int, npf_addr_t *);
215 217
@@ -331,27 +333,26 @@ void npf_state_destroy(npf_state_t *); @@ -331,27 +333,26 @@ void npf_state_destroy(npf_state_t *);
331bool npf_state_tcp(npf_cache_t *, nbuf_t *, npf_state_t *, int); 333bool npf_state_tcp(npf_cache_t *, nbuf_t *, npf_state_t *, int);
332int npf_state_tcp_timeout(const npf_state_t *); 334int npf_state_tcp_timeout(const npf_state_t *);
333 335
334/* NAT. */ 336/* NAT. */
335void npf_nat_sysinit(void); 337void npf_nat_sysinit(void);
336void npf_nat_sysfini(void); 338void npf_nat_sysfini(void);
337npf_natpolicy_t *npf_nat_newpolicy(prop_dictionary_t, npf_ruleset_t *); 339npf_natpolicy_t *npf_nat_newpolicy(prop_dictionary_t, npf_ruleset_t *);
338void npf_nat_freepolicy(npf_natpolicy_t *); 340void npf_nat_freepolicy(npf_natpolicy_t *);
339bool npf_nat_matchpolicy(npf_natpolicy_t *, npf_natpolicy_t *); 341bool npf_nat_matchpolicy(npf_natpolicy_t *, npf_natpolicy_t *);
340bool npf_nat_sharepm(npf_natpolicy_t *, npf_natpolicy_t *); 342bool npf_nat_sharepm(npf_natpolicy_t *, npf_natpolicy_t *);
341void npf_nat_freealg(npf_natpolicy_t *, npf_alg_t *); 343void npf_nat_freealg(npf_natpolicy_t *, npf_alg_t *);
342 344
343int npf_do_nat(npf_cache_t *, npf_session_t *, nbuf_t *, const int); 345int npf_do_nat(npf_cache_t *, npf_session_t *, nbuf_t *, const int);
344int npf_nat_translate(npf_cache_t *, nbuf_t *, npf_nat_t *, bool); 
345void npf_nat_destroy(npf_nat_t *); 346void npf_nat_destroy(npf_nat_t *);
346void npf_nat_getorig(npf_nat_t *, npf_addr_t **, in_port_t *); 347void npf_nat_getorig(npf_nat_t *, npf_addr_t **, in_port_t *);
347void npf_nat_gettrans(npf_nat_t *, npf_addr_t **, in_port_t *); 348void npf_nat_gettrans(npf_nat_t *, npf_addr_t **, in_port_t *);
348void npf_nat_setalg(npf_nat_t *, npf_alg_t *, uintptr_t); 349void npf_nat_setalg(npf_nat_t *, npf_alg_t *, uintptr_t);
349 350
350int npf_nat_save(prop_dictionary_t, prop_array_t, npf_nat_t *); 351int npf_nat_save(prop_dictionary_t, prop_array_t, npf_nat_t *);
351npf_nat_t * npf_nat_restore(prop_dictionary_t, npf_session_t *); 352npf_nat_t * npf_nat_restore(prop_dictionary_t, npf_session_t *);
352 353
353/* ALG interface. */ 354/* ALG interface. */
354void npf_alg_sysinit(void); 355void npf_alg_sysinit(void);
355void npf_alg_sysfini(void); 356void npf_alg_sysfini(void);
356npf_alg_t * npf_alg_register(const char *, const npfa_funcs_t *); 357npf_alg_t * npf_alg_register(const char *, const npfa_funcs_t *);
357int npf_alg_unregister(npf_alg_t *); 358int npf_alg_unregister(npf_alg_t *);

cvs diff -r1.29 -r1.30 src/sys/net/npf/npf_inet.c (expand / switch to unified diff)

--- src/sys/net/npf/npf_inet.c 2014/02/13 03:34:40 1.29
+++ src/sys/net/npf/npf_inet.c 2014/02/19 03:51:31 1.30
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: npf_inet.c,v 1.29 2014/02/13 03:34:40 rmind Exp $ */ 1/* $NetBSD: npf_inet.c,v 1.30 2014/02/19 03:51:31 rmind Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2009-2014 The NetBSD Foundation, Inc. 4 * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This material is based upon work partially supported by The 7 * This material is based upon work partially supported by The
8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. 8 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -29,27 +29,27 @@ @@ -29,27 +29,27 @@
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32/* 32/*
33 * Various protocol related helper routines. 33 * Various protocol related helper routines.
34 * 34 *
35 * This layer manipulates npf_cache_t structure i.e. caches requested headers 35 * This layer manipulates npf_cache_t structure i.e. caches requested headers
36 * and stores which information was cached in the information bit field. 36 * and stores which information was cached in the information bit field.
37 * It is also responsibility of this layer to update or invalidate the cache 37 * It is also responsibility of this layer to update or invalidate the cache
38 * on rewrites (e.g. by translation routines). 38 * on rewrites (e.g. by translation routines).
39 */ 39 */
40 40
41#include <sys/cdefs.h> 41#include <sys/cdefs.h>
42__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.29 2014/02/13 03:34:40 rmind Exp $"); 42__KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.30 2014/02/19 03:51:31 rmind Exp $");
43 43
44#include <sys/param.h> 44#include <sys/param.h>
45#include <sys/types.h> 45#include <sys/types.h>
46 46
47#include <net/pfil.h> 47#include <net/pfil.h>
48#include <net/if.h> 48#include <net/if.h>
49#include <net/ethertypes.h> 49#include <net/ethertypes.h>
50#include <net/if_ether.h> 50#include <net/if_ether.h>
51 51
52#include <netinet/in_systm.h> 52#include <netinet/in_systm.h>
53#include <netinet/in.h> 53#include <netinet/in.h>
54#include <netinet/ip.h> 54#include <netinet/ip.h>
55#include <netinet/ip6.h> 55#include <netinet/ip6.h>
@@ -568,27 +568,27 @@ npf_rwrcksum(const npf_cache_t *npc, u_i @@ -568,27 +568,27 @@ npf_rwrcksum(const npf_cache_t *npc, u_i
568 568
569 if (npf_iscached(npc, NPC_IP4)) { 569 if (npf_iscached(npc, NPC_IP4)) {
570 struct ip *ip = npc->npc_ip.v4; 570 struct ip *ip = npc->npc_ip.v4;
571 uint16_t ipsum = ip->ip_sum; 571 uint16_t ipsum = ip->ip_sum;
572 572
573 /* Recalculate IPv4 checksum and rewrite. */ 573 /* Recalculate IPv4 checksum and rewrite. */
574 ip->ip_sum = npf_addr_cksum(ipsum, alen, oaddr, addr); 574 ip->ip_sum = npf_addr_cksum(ipsum, alen, oaddr, addr);
575 } else { 575 } else {
576 /* No checksum for IPv6. */ 576 /* No checksum for IPv6. */
577 KASSERT(npf_iscached(npc, NPC_IP6)); 577 KASSERT(npf_iscached(npc, NPC_IP6));
578 } 578 }
579 579
580 /* Nothing else to do for ICMP. */ 580 /* Nothing else to do for ICMP. */
581 if (proto == IPPROTO_ICMP) { 581 if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
582 return true; 582 return true;
583 } 583 }
584 KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP)); 584 KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
585 585
586 /* 586 /*
587 * Calculate TCP/UDP checksum: 587 * Calculate TCP/UDP checksum:
588 * - Skip if UDP and the current checksum is zero. 588 * - Skip if UDP and the current checksum is zero.
589 * - Fixup the IP address change. 589 * - Fixup the IP address change.
590 * - Fixup the port change, if required (non-zero). 590 * - Fixup the port change, if required (non-zero).
591 */ 591 */
592 if (proto == IPPROTO_TCP) { 592 if (proto == IPPROTO_TCP) {
593 struct tcphdr *th = npc->npc_l4.tcp; 593 struct tcphdr *th = npc->npc_l4.tcp;
594 594
@@ -607,26 +607,70 @@ npf_rwrcksum(const npf_cache_t *npc, u_i @@ -607,26 +607,70 @@ npf_rwrcksum(const npf_cache_t *npc, u_i
607 } 607 }
608 608
609 uint16_t cksum = npf_addr_cksum(*ocksum, alen, oaddr, addr); 609 uint16_t cksum = npf_addr_cksum(*ocksum, alen, oaddr, addr);
610 if (port) { 610 if (port) {
611 cksum = npf_fixup16_cksum(cksum, oport, port); 611 cksum = npf_fixup16_cksum(cksum, oport, port);
612 } 612 }
613 613
614 /* Rewrite TCP/UDP checksum. */ 614 /* Rewrite TCP/UDP checksum. */
615 memcpy(ocksum, &cksum, sizeof(uint16_t)); 615 memcpy(ocksum, &cksum, sizeof(uint16_t));
616 return true; 616 return true;
617} 617}
618 618
619/* 619/*
 620 * npf_napt_rwr: perform address and/or port translation.
 621 */
 622int
 623npf_napt_rwr(const npf_cache_t *npc, u_int which,
 624 const npf_addr_t *addr, const in_addr_t port)
 625{
 626 const unsigned proto = npc->npc_proto;
 627
 628 /*
 629 * Rewrite IP and/or TCP/UDP checksums first, since we need the
 630 * current (old) address/port for the calculations. Then perform
 631 * the address translation i.e. rewrite source or destination.
 632 */
 633 if (!npf_rwrcksum(npc, which, addr, port)) {
 634 return EINVAL;
 635 }
 636 if (!npf_rwrip(npc, which, addr)) {
 637 return EINVAL;
 638 }
 639 if (port == 0) {
 640 /* Done. */
 641 return 0;
 642 }
 643
 644 switch (proto) {
 645 case IPPROTO_TCP:
 646 case IPPROTO_UDP:
 647 /* Rewrite source/destination port. */
 648 if (!npf_rwrport(npc, which, port)) {
 649 return EINVAL;
 650 }
 651 break;
 652 case IPPROTO_ICMP:
 653 case IPPROTO_ICMPV6:
 654 KASSERT(npf_iscached(npc, NPC_ICMP));
 655 /* Nothing. */
 656 break;
 657 default:
 658 return ENOTSUP;
 659 }
 660 return 0;
 661}
 662
 663/*
620 * IPv6-to-IPv6 Network Prefix Translation (NPTv6), as per RFC 6296. 664 * IPv6-to-IPv6 Network Prefix Translation (NPTv6), as per RFC 6296.
621 */ 665 */
622 666
623int 667int
624npf_npt66_rwr(const npf_cache_t *npc, u_int which, const npf_addr_t *pref, 668npf_npt66_rwr(const npf_cache_t *npc, u_int which, const npf_addr_t *pref,
625 npf_netmask_t len, uint16_t adj) 669 npf_netmask_t len, uint16_t adj)
626{ 670{
627 npf_addr_t *addr = npc->npc_ips[which]; 671 npf_addr_t *addr = npc->npc_ips[which];
628 unsigned remnant, word, preflen = len >> 4; 672 unsigned remnant, word, preflen = len >> 4;
629 uint32_t sum; 673 uint32_t sum;
630 674
631 KASSERT(which == NPF_SRC || which == NPF_DST); 675 KASSERT(which == NPF_SRC || which == NPF_DST);
632 676

cvs diff -r1.25 -r1.26 src/sys/net/npf/npf_nat.c (expand / switch to unified diff)

--- src/sys/net/npf/npf_nat.c 2014/02/13 03:34:40 1.25
+++ src/sys/net/npf/npf_nat.c 2014/02/19 03:51:31 1.26
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: npf_nat.c,v 1.25 2014/02/13 03:34:40 rmind Exp $ */ 1/* $NetBSD: npf_nat.c,v 1.26 2014/02/19 03:51:31 rmind Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2014 Mindaugas Rasiukevicius <rmind at netbsd org> 4 * Copyright (c) 2014 Mindaugas Rasiukevicius <rmind at netbsd org>
5 * Copyright (c) 2010-2013 The NetBSD Foundation, Inc. 5 * Copyright (c) 2010-2013 The NetBSD Foundation, Inc.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * This material is based upon work partially supported by The 8 * This material is based upon work partially supported by The
9 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius. 9 * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -61,27 +61,27 @@ @@ -61,27 +61,27 @@
61 * 61 *
62 * Sessions, translation entries and their life-cycle 62 * Sessions, translation entries and their life-cycle
63 * 63 *
64 * NAT module relies on session management module. Each translated 64 * NAT module relies on session management module. Each translated
65 * session has an associated translation entry (npf_nat_t), which 65 * session has an associated translation entry (npf_nat_t), which
66 * contains information used for backwards stream translation, i.e. 66 * contains information used for backwards stream translation, i.e.
67 * original IP address with port and translation port, allocated from 67 * original IP address with port and translation port, allocated from
68 * the port map. Each NAT entry is associated with the policy, which 68 * the port map. Each NAT entry is associated with the policy, which
69 * contains translation IP address. Allocated port is returned to the 69 * contains translation IP address. Allocated port is returned to the
70 * port map and NAT entry is destroyed when session expires. 70 * port map and NAT entry is destroyed when session expires.
71 */ 71 */
72 72
73#include <sys/cdefs.h> 73#include <sys/cdefs.h>
74__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.25 2014/02/13 03:34:40 rmind Exp $"); 74__KERNEL_RCSID(0, "$NetBSD: npf_nat.c,v 1.26 2014/02/19 03:51:31 rmind Exp $");
75 75
76#include <sys/param.h> 76#include <sys/param.h>
77#include <sys/types.h> 77#include <sys/types.h>
78 78
79#include <sys/atomic.h> 79#include <sys/atomic.h>
80#include <sys/bitops.h> 80#include <sys/bitops.h>
81#include <sys/condvar.h> 81#include <sys/condvar.h>
82#include <sys/kmem.h> 82#include <sys/kmem.h>
83#include <sys/mutex.h> 83#include <sys/mutex.h>
84#include <sys/pool.h> 84#include <sys/pool.h>
85#include <sys/proc.h> 85#include <sys/proc.h>
86#include <sys/cprng.h> 86#include <sys/cprng.h>
87 87
@@ -539,121 +539,78 @@ npf_nat_create(npf_cache_t *npc, npf_nat @@ -539,121 +539,78 @@ npf_nat_create(npf_cache_t *npc, npf_nat
539 if ((np->n_flags & NPF_NAT_PORTMAP) != 0) { 539 if ((np->n_flags & NPF_NAT_PORTMAP) != 0) {
540 nt->nt_tport = npf_nat_getport(np); 540 nt->nt_tport = npf_nat_getport(np);
541 } else { 541 } else {
542 nt->nt_tport = np->n_tport; 542 nt->nt_tport = np->n_tport;
543 } 543 }
544out: 544out:
545 mutex_enter(&np->n_lock); 545 mutex_enter(&np->n_lock);
546 LIST_INSERT_HEAD(&np->n_nat_list, nt, nt_entry); 546 LIST_INSERT_HEAD(&np->n_nat_list, nt, nt_entry);
547 mutex_exit(&np->n_lock); 547 mutex_exit(&np->n_lock);
548 return nt; 548 return nt;
549} 549}
550 550
551/* 551/*
552 * npf_nat_rwr: perform address and/or port translation. 
553 */ 
554static int 
555npf_nat_rwr(npf_cache_t *npc, const npf_natpolicy_t *np, 
556 const npf_addr_t *addr, const in_addr_t port, bool forw) 
557{ 
558 const unsigned proto = npc->npc_proto; 
559 const u_int which = npf_nat_which(np->n_type, forw); 
560 
561 /* 
562 * Rewrite IP and/or TCP/UDP checksums first, since we need the 
563 * current (old) address/port for the calculations. Then perform 
564 * the address translation i.e. rewrite source or destination. 
565 */ 
566 if (!npf_rwrcksum(npc, which, addr, port)) { 
567 return EINVAL; 
568 } 
569 if (!npf_rwrip(npc, which, addr)) { 
570 return EINVAL; 
571 } 
572 if ((np->n_flags & NPF_NAT_PORTS) == 0) { 
573 /* Done. */ 
574 return 0; 
575 } 
576 
577 switch (proto) { 
578 case IPPROTO_TCP: 
579 case IPPROTO_UDP: 
580 /* Rewrite source/destination port. */ 
581 if (!npf_rwrport(npc, which, port)) { 
582 return EINVAL; 
583 } 
584 break; 
585 case IPPROTO_ICMP: 
586 KASSERT(npf_iscached(npc, NPC_ICMP)); 
587 /* Nothing. */ 
588 break; 
589 default: 
590 return ENOTSUP; 
591 } 
592 return 0; 
593} 
594 
595/* 
596 * npf_nat_translate: perform translation given the state data. 552 * npf_nat_translate: perform translation given the state data.
597 */ 553 */
598int 554static inline int
599npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw) 555npf_nat_translate(npf_cache_t *npc, nbuf_t *nbuf, npf_nat_t *nt, bool forw)
600{ 556{
601 const npf_natpolicy_t *np = nt->nt_natpolicy; 557 const npf_natpolicy_t *np = nt->nt_natpolicy;
 558 const u_int which = npf_nat_which(np->n_type, forw);
602 const npf_addr_t *addr; 559 const npf_addr_t *addr;
603 in_port_t port; 560 in_port_t port;
604 561
605 KASSERT(npf_iscached(npc, NPC_IP46)); 562 KASSERT(npf_iscached(npc, NPC_IP46));
606 KASSERT(npf_iscached(npc, NPC_LAYER4)); 563 KASSERT(npf_iscached(npc, NPC_LAYER4));
607 KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)); 
608 564
609 if (forw) { 565 if (forw) {
610 /* "Forwards" stream: use translation address/port. */ 566 /* "Forwards" stream: use translation address/port. */
611 addr = &np->n_taddr; 567 addr = &np->n_taddr;
612 port = nt->nt_tport; 568 port = nt->nt_tport;
613 } else { 569 } else {
614 /* "Backwards" stream: use original address/port. */ 570 /* "Backwards" stream: use original address/port. */
615 addr = &nt->nt_oaddr; 571 addr = &nt->nt_oaddr;
616 port = nt->nt_oport; 572 port = nt->nt_oport;
617 } 573 }
618 KASSERT((np->n_flags & NPF_NAT_PORTS) != 0 || port == 0); 574 KASSERT((np->n_flags & NPF_NAT_PORTS) != 0 || port == 0);
619 575
620 /* Execute ALG hook first. */ 576 /* Execute ALG translation first. */
621 if ((npc->npc_info & NPC_ALG_EXEC) == 0) { 577 if ((npc->npc_info & NPC_ALG_EXEC) == 0) {
622 npc->npc_info |= NPC_ALG_EXEC; 578 npc->npc_info |= NPC_ALG_EXEC;
623 npf_alg_exec(npc, nbuf, nt, forw); 579 npf_alg_exec(npc, nbuf, nt, forw);
 580 npf_recache(npc, nbuf);
624 } 581 }
 582 KASSERT(!nbuf_flag_p(nbuf, NBUF_DATAREF_RESET));
625 583
626 /* Finally, perform the translation. */ 584 /* Finally, perform the translation. */
627 return npf_nat_rwr(npc, np, addr, port, forw); 585 return npf_napt_rwr(npc, which, addr, port);
628} 586}
629 587
630/* 588/*
631 * npf_nat_algo: perform the translation given the algorithm. 589 * npf_nat_algo: perform the translation given the algorithm.
632 */ 590 */
633static inline int  591static inline int
634npf_nat_algo(npf_cache_t *npc, const npf_natpolicy_t *np, bool forw) 592npf_nat_algo(npf_cache_t *npc, const npf_natpolicy_t *np, bool forw)
635{ 593{
636 u_int which; 594 const u_int which = npf_nat_which(np->n_type, forw);
637 int error; 595 int error;
638 596
639 switch (np->n_algo) { 597 switch (np->n_algo) {
640 case NPF_ALGO_NPT66: 598 case NPF_ALGO_NPT66:
641 which = npf_nat_which(np->n_type, forw); 
642 error = npf_npt66_rwr(npc, which, &np->n_taddr, 599 error = npf_npt66_rwr(npc, which, &np->n_taddr,
643 np->n_tmask, np->n_npt66_adj); 600 np->n_tmask, np->n_npt66_adj);
644 break; 601 break;
645 default: 602 default:
646 error = npf_nat_rwr(npc, np, &np->n_taddr, np->n_tport, forw); 603 error = npf_napt_rwr(npc, which, &np->n_taddr, np->n_tport);
647 break; 604 break;
648 } 605 }
649 606
650 return error; 607 return error;
651}  608}
652 609
653/* 610/*
654 * npf_do_nat: 611 * npf_do_nat:
655 * - Inspect packet for a NAT policy, unless a session with a NAT 612 * - Inspect packet for a NAT policy, unless a session with a NAT
656 * association already exists. In such case, determine whether it 613 * association already exists. In such case, determine whether it
657 * is a "forwards" or "backwards" stream. 614 * is a "forwards" or "backwards" stream.
658 * - Perform translation: rewrite source or destination fields, 615 * - Perform translation: rewrite source or destination fields,
659 * depending on translation type and direction. 616 * depending on translation type and direction.