1 /*	$NetBSD: npf_inet.c,v 1.34 2016/03/18 10:09:46 mrg Exp $	*/
2 
3 /*-
4  * Copyright (c) 2009-2014 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This material is based upon work partially supported by The
8  * NetBSD Foundation under a contract with Mindaugas Rasiukevicius.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
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
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
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Various protocol related helper routines.
34  *
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.
37  * It is also responsibility of this layer to update or invalidate the cache
38  * on rewrites (e.g. by translation routines).
39  */
40 
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: npf_inet.c,v 1.34 2016/03/18 10:09:46 mrg Exp $");
43 
44 #include <sys/param.h>
45 #include <sys/types.h>
46 
47 #include <net/pfil.h>
48 #include <net/if.h>
49 #include <net/ethertypes.h>
50 #include <net/if_ether.h>
51 
52 #include <netinet/in_systm.h>
53 #include <netinet/in.h>
54 #include <netinet6/in6_var.h>
55 #include <netinet/ip.h>
56 #include <netinet/ip6.h>
57 #include <netinet/tcp.h>
58 #include <netinet/udp.h>
59 #include <netinet/ip_icmp.h>
60 
61 #include "npf_impl.h"
62 
63 /*
64  * npf_fixup{16,32}_cksum: incremental update of the Internet checksum.
65  */
66 
67 uint16_t
npf_fixup16_cksum(uint16_t cksum,uint16_t odatum,uint16_t ndatum)68 npf_fixup16_cksum(uint16_t cksum, uint16_t odatum, uint16_t ndatum)
69 {
70 	uint32_t sum;
71 
72 	/*
73 	 * RFC 1624:
74 	 *	HC' = ~(~HC + ~m + m')
75 	 *
76 	 * Note: 1's complement sum is endian-independent (RFC 1071, page 2).
77 	 */
78 	sum = ~cksum & 0xffff;
79 	sum += (~odatum & 0xffff) + ndatum;
80 	sum = (sum >> 16) + (sum & 0xffff);
81 	sum += (sum >> 16);
82 
83 	return ~sum & 0xffff;
84 }
85 
86 uint16_t
npf_fixup32_cksum(uint16_t cksum,uint32_t odatum,uint32_t ndatum)87 npf_fixup32_cksum(uint16_t cksum, uint32_t odatum, uint32_t ndatum)
88 {
89 	uint32_t sum;
90 
91 	/*
92 	 * Checksum 32-bit datum as as two 16-bit.  Note, the first
93 	 * 32->16 bit reduction is not necessary.
94 	 */
95 	sum = ~cksum & 0xffff;
96 	sum += (~odatum & 0xffff) + (ndatum & 0xffff);
97 
98 	sum += (~odatum >> 16) + (ndatum >> 16);
99 	sum = (sum >> 16) + (sum & 0xffff);
100 	sum += (sum >> 16);
101 	return ~sum & 0xffff;
102 }
103 
104 /*
105  * npf_addr_cksum: calculate checksum of the address, either IPv4 or IPv6.
106  */
107 uint16_t
npf_addr_cksum(uint16_t cksum,int sz,const npf_addr_t * oaddr,const npf_addr_t * naddr)108 npf_addr_cksum(uint16_t cksum, int sz, const npf_addr_t *oaddr,
109     const npf_addr_t *naddr)
110 {
111 	const uint32_t *oip32 = (const uint32_t *)oaddr;
112 	const uint32_t *nip32 = (const uint32_t *)naddr;
113 
114 	KASSERT(sz % sizeof(uint32_t) == 0);
115 	do {
116 		cksum = npf_fixup32_cksum(cksum, *oip32++, *nip32++);
117 		sz -= sizeof(uint32_t);
118 	} while (sz);
119 
120 	return cksum;
121 }
122 
123 /*
124  * npf_addr_sum: provide IP addresses as a XORed 32-bit integer.
125  * Note: used for hash function.
126  */
127 uint32_t
npf_addr_mix(const int sz,const npf_addr_t * a1,const npf_addr_t * a2)128 npf_addr_mix(const int sz, const npf_addr_t *a1, const npf_addr_t *a2)
129 {
130 	uint32_t mix = 0;
131 
132 	KASSERT(sz > 0 && a1 != NULL && a2 != NULL);
133 
134 	for (int i = 0; i < (sz >> 2); i++) {
135 		mix ^= a1->s6_addr32[i];
136 		mix ^= a2->s6_addr32[i];
137 	}
138 	return mix;
139 }
140 
141 /*
142  * npf_addr_mask: apply the mask to a given address and store the result.
143  */
144 void
npf_addr_mask(const npf_addr_t * addr,const npf_netmask_t mask,const int alen,npf_addr_t * out)145 npf_addr_mask(const npf_addr_t *addr, const npf_netmask_t mask,
146     const int alen, npf_addr_t *out)
147 {
148 	const int nwords = alen >> 2;
149 	uint_fast8_t length = mask;
150 
151 	/* Note: maximum length is 32 for IPv4 and 128 for IPv6. */
152 	KASSERT(length <= NPF_MAX_NETMASK);
153 
154 	for (int i = 0; i < nwords; i++) {
155 		uint32_t wordmask;
156 
157 		if (length >= 32) {
158 			wordmask = htonl(0xffffffff);
159 			length -= 32;
160 		} else if (length) {
161 			wordmask = htonl(0xffffffff << (32 - length));
162 			length = 0;
163 		} else {
164 			wordmask = 0;
165 		}
166 		out->s6_addr32[i] = addr->s6_addr32[i] & wordmask;
167 	}
168 }
169 
170 /*
171  * npf_addr_cmp: compare two addresses, either IPv4 or IPv6.
172  *
173  * => Return 0 if equal and negative/positive if less/greater accordingly.
174  * => Ignore the mask, if NPF_NO_NETMASK is specified.
175  */
176 int
npf_addr_cmp(const npf_addr_t * addr1,const npf_netmask_t mask1,const npf_addr_t * addr2,const npf_netmask_t mask2,const int alen)177 npf_addr_cmp(const npf_addr_t *addr1, const npf_netmask_t mask1,
178     const npf_addr_t *addr2, const npf_netmask_t mask2, const int alen)
179 {
180 	npf_addr_t realaddr1, realaddr2;
181 
182 	if (mask1 != NPF_NO_NETMASK) {
183 		npf_addr_mask(addr1, mask1, alen, &realaddr1);
184 		addr1 = &realaddr1;
185 	}
186 	if (mask2 != NPF_NO_NETMASK) {
187 		npf_addr_mask(addr2, mask2, alen, &realaddr2);
188 		addr2 = &realaddr2;
189 	}
190 	return memcmp(addr1, addr2, alen);
191 }
192 
193 /*
194  * npf_tcpsaw: helper to fetch SEQ, ACK, WIN and return TCP data length.
195  *
196  * => Returns all values in host byte-order.
197  */
198 int
npf_tcpsaw(const npf_cache_t * npc,tcp_seq * seq,tcp_seq * ack,uint32_t * win)199 npf_tcpsaw(const npf_cache_t *npc, tcp_seq *seq, tcp_seq *ack, uint32_t *win)
200 {
201 	const struct tcphdr *th = npc->npc_l4.tcp;
202 	u_int thlen;
203 
204 	KASSERT(npf_iscached(npc, NPC_TCP));
205 
206 	*seq = ntohl(th->th_seq);
207 	*ack = ntohl(th->th_ack);
208 	*win = (uint32_t)ntohs(th->th_win);
209 	thlen = th->th_off << 2;
210 
211 	if (npf_iscached(npc, NPC_IP4)) {
212 		const struct ip *ip = npc->npc_ip.v4;
213 		return ntohs(ip->ip_len) - npc->npc_hlen - thlen;
214 	} else if (npf_iscached(npc, NPC_IP6)) {
215 		const struct ip6_hdr *ip6 = npc->npc_ip.v6;
216 		return ntohs(ip6->ip6_plen) - thlen;
217 	}
218 	return 0;
219 }
220 
221 /*
222  * npf_fetch_tcpopts: parse and return TCP options.
223  */
224 bool
npf_fetch_tcpopts(npf_cache_t * npc,uint16_t * mss,int * wscale)225 npf_fetch_tcpopts(npf_cache_t *npc, uint16_t *mss, int *wscale)
226 {
227 	nbuf_t *nbuf = npc->npc_nbuf;
228 	const struct tcphdr *th = npc->npc_l4.tcp;
229 	int topts_len, step;
230 	void *nptr;
231 	uint8_t val;
232 	bool ok;
233 
234 	KASSERT(npf_iscached(npc, NPC_IP46));
235 	KASSERT(npf_iscached(npc, NPC_TCP));
236 
237 	/* Determine if there are any TCP options, get their length. */
238 	topts_len = (th->th_off << 2) - sizeof(struct tcphdr);
239 	if (topts_len <= 0) {
240 		/* No options. */
241 		return false;
242 	}
243 	KASSERT(topts_len <= MAX_TCPOPTLEN);
244 
245 	/* First step: IP and TCP header up to options. */
246 	step = npc->npc_hlen + sizeof(struct tcphdr);
247 	nbuf_reset(nbuf);
248 next:
249 	if ((nptr = nbuf_advance(nbuf, step, 1)) == NULL) {
250 		ok = false;
251 		goto done;
252 	}
253 	val = *(uint8_t *)nptr;
254 
255 	switch (val) {
256 	case TCPOPT_EOL:
257 		/* Done. */
258 		ok = true;
259 		goto done;
260 	case TCPOPT_NOP:
261 		topts_len--;
262 		step = 1;
263 		break;
264 	case TCPOPT_MAXSEG:
265 		if ((nptr = nbuf_advance(nbuf, 2, 2)) == NULL) {
266 			ok = false;
267 			goto done;
268 		}
269 		if (mss) {
270 			if (*mss) {
271 				memcpy(nptr, mss, sizeof(uint16_t));
272 			} else {
273 				memcpy(mss, nptr, sizeof(uint16_t));
274 			}
275 		}
276 		topts_len -= TCPOLEN_MAXSEG;
277 		step = 2;
278 		break;
279 	case TCPOPT_WINDOW:
280 		/* TCP Window Scaling (RFC 1323). */
281 		if ((nptr = nbuf_advance(nbuf, 2, 1)) == NULL) {
282 			ok = false;
283 			goto done;
284 		}
285 		val = *(uint8_t *)nptr;
286 		*wscale = (val > TCP_MAX_WINSHIFT) ? TCP_MAX_WINSHIFT : val;
287 		topts_len -= TCPOLEN_WINDOW;
288 		step = 1;
289 		break;
290 	default:
291 		if ((nptr = nbuf_advance(nbuf, 1, 1)) == NULL) {
292 			ok = false;
293 			goto done;
294 		}
295 		val = *(uint8_t *)nptr;
296 		if (val < 2 || val > topts_len) {
297 			ok = false;
298 			goto done;
299 		}
300 		topts_len -= val;
301 		step = val - 1;
302 	}
303 
304 	/* Any options left? */
305 	if (__predict_true(topts_len > 0)) {
306 		goto next;
307 	}
308 	ok = true;
309 done:
310 	if (nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)) {
311 		npf_recache(npc);
312 	}
313 	return ok;
314 }
315 
316 static int
npf_cache_ip(npf_cache_t * npc,nbuf_t * nbuf)317 npf_cache_ip(npf_cache_t *npc, nbuf_t *nbuf)
318 {
319 	const void *nptr = nbuf_dataptr(nbuf);
320 	const uint8_t ver = *(const uint8_t *)nptr;
321 	int flags = 0;
322 
323 	switch (ver >> 4) {
324 	case IPVERSION: {
325 		struct ip *ip;
326 
327 		ip = nbuf_ensure_contig(nbuf, sizeof(struct ip));
328 		if (ip == NULL) {
329 			return 0;
330 		}
331 
332 		/* Check header length and fragment offset. */
333 		if ((u_int)(ip->ip_hl << 2) < sizeof(struct ip)) {
334 			return 0;
335 		}
336 		if (ip->ip_off & ~htons(IP_DF | IP_RF)) {
337 			/* Note fragmentation. */
338 			flags |= NPC_IPFRAG;
339 		}
340 
341 		/* Cache: layer 3 - IPv4. */
342 		npc->npc_alen = sizeof(struct in_addr);
343 		npc->npc_ips[NPF_SRC] = (npf_addr_t *)&ip->ip_src;
344 		npc->npc_ips[NPF_DST] = (npf_addr_t *)&ip->ip_dst;
345 		npc->npc_hlen = ip->ip_hl << 2;
346 		npc->npc_proto = ip->ip_p;
347 
348 		npc->npc_ip.v4 = ip;
349 		flags |= NPC_IP4;
350 		break;
351 	}
352 
353 	case (IPV6_VERSION >> 4): {
354 		struct ip6_hdr *ip6;
355 		struct ip6_ext *ip6e;
356 		size_t off, hlen;
357 
358 		ip6 = nbuf_ensure_contig(nbuf, sizeof(struct ip6_hdr));
359 		if (ip6 == NULL) {
360 			return 0;
361 		}
362 
363 		/* Set initial next-protocol value. */
364 		hlen = sizeof(struct ip6_hdr);
365 		npc->npc_proto = ip6->ip6_nxt;
366 		npc->npc_hlen = hlen;
367 
368 		/*
369 		 * Advance by the length of the current header.
370 		 */
371 		off = nbuf_offset(nbuf);
372 		while (nbuf_advance(nbuf, hlen, 0) != NULL) {
373 			ip6e = nbuf_ensure_contig(nbuf, sizeof(*ip6e));
374 			if (ip6e == NULL) {
375 				return 0;
376 			}
377 
378 			/*
379 			 * Determine whether we are going to continue.
380 			 */
381 			switch (npc->npc_proto) {
382 			case IPPROTO_HOPOPTS:
383 			case IPPROTO_DSTOPTS:
384 			case IPPROTO_ROUTING:
385 				hlen = (ip6e->ip6e_len + 1) << 3;
386 				break;
387 			case IPPROTO_FRAGMENT:
388 				hlen = sizeof(struct ip6_frag);
389 				flags |= NPC_IPFRAG;
390 				break;
391 			case IPPROTO_AH:
392 				hlen = (ip6e->ip6e_len + 2) << 2;
393 				break;
394 			default:
395 				hlen = 0;
396 				break;
397 			}
398 
399 			if (!hlen) {
400 				break;
401 			}
402 			npc->npc_proto = ip6e->ip6e_nxt;
403 			npc->npc_hlen += hlen;
404 		}
405 
406 		/*
407 		 * Re-fetch the header pointers (nbufs might have been
408 		 * reallocated).  Restore the original offset (if any).
409 		 */
410 		nbuf_reset(nbuf);
411 		ip6 = nbuf_dataptr(nbuf);
412 		if (off) {
413 			nbuf_advance(nbuf, off, 0);
414 		}
415 
416 		/* Cache: layer 3 - IPv6. */
417 		npc->npc_alen = sizeof(struct in6_addr);
418 		npc->npc_ips[NPF_SRC] = (npf_addr_t *)&ip6->ip6_src;
419 		npc->npc_ips[NPF_DST]= (npf_addr_t *)&ip6->ip6_dst;
420 
421 		npc->npc_ip.v6 = ip6;
422 		flags |= NPC_IP6;
423 		break;
424 	}
425 	default:
426 		break;
427 	}
428 	return flags;
429 }
430 
431 /*
432  * npf_cache_all: general routine to cache all relevant IP (v4 or v6)
433  * and TCP, UDP or ICMP headers.
434  *
435  * => nbuf offset shall be set accordingly.
436  */
437 int
npf_cache_all(npf_cache_t * npc)438 npf_cache_all(npf_cache_t *npc)
439 {
440 	nbuf_t *nbuf = npc->npc_nbuf;
441 	int flags, l4flags;
442 	u_int hlen;
443 
444 	/*
445 	 * This routine is a main point where the references are cached,
446 	 * therefore clear the flag as we reset.
447 	 */
448 again:
449 	nbuf_unset_flag(nbuf, NBUF_DATAREF_RESET);
450 
451 	/*
452 	 * First, cache the L3 header (IPv4 or IPv6).  If IP packet is
453 	 * fragmented, then we cannot look into L4.
454 	 */
455 	flags = npf_cache_ip(npc, nbuf);
456 	if ((flags & NPC_IP46) == 0 || (flags & NPC_IPFRAG) != 0) {
457 		nbuf_unset_flag(nbuf, NBUF_DATAREF_RESET);
458 		npc->npc_info |= flags;
459 		return flags;
460 	}
461 	hlen = npc->npc_hlen;
462 
463 	switch (npc->npc_proto) {
464 	case IPPROTO_TCP:
465 		/* Cache: layer 4 - TCP. */
466 		npc->npc_l4.tcp = nbuf_advance(nbuf, hlen,
467 		    sizeof(struct tcphdr));
468 		l4flags = NPC_LAYER4 | NPC_TCP;
469 		break;
470 	case IPPROTO_UDP:
471 		/* Cache: layer 4 - UDP. */
472 		npc->npc_l4.udp = nbuf_advance(nbuf, hlen,
473 		    sizeof(struct udphdr));
474 		l4flags = NPC_LAYER4 | NPC_UDP;
475 		break;
476 	case IPPROTO_ICMP:
477 		/* Cache: layer 4 - ICMPv4. */
478 		npc->npc_l4.icmp = nbuf_advance(nbuf, hlen,
479 		    offsetof(struct icmp, icmp_void));
480 		l4flags = NPC_LAYER4 | NPC_ICMP;
481 		break;
482 	case IPPROTO_ICMPV6:
483 		/* Cache: layer 4 - ICMPv6. */
484 		npc->npc_l4.icmp6 = nbuf_advance(nbuf, hlen,
485 		    offsetof(struct icmp6_hdr, icmp6_data32));
486 		l4flags = NPC_LAYER4 | NPC_ICMP;
487 		break;
488 	default:
489 		l4flags = 0;
490 		break;
491 	}
492 
493 	if (nbuf_flag_p(nbuf, NBUF_DATAREF_RESET)) {
494 		goto again;
495 	}
496 
497 	/* Add the L4 flags if nbuf_advance() succeeded. */
498 	if (l4flags && npc->npc_l4.hdr) {
499 		flags |= l4flags;
500 	}
501 	npc->npc_info |= flags;
502 	return flags;
503 }
504 
505 void
npf_recache(npf_cache_t * npc)506 npf_recache(npf_cache_t *npc)
507 {
508 	nbuf_t *nbuf = npc->npc_nbuf;
509 	const int mflags __diagused = npc->npc_info & (NPC_IP46 | NPC_LAYER4);
510 	int flags __diagused;
511 
512 	nbuf_reset(nbuf);
513 	npc->npc_info = 0;
514 	flags = npf_cache_all(npc);
515 
516 	KASSERT((flags & mflags) == mflags);
517 	KASSERT(nbuf_flag_p(nbuf, NBUF_DATAREF_RESET) == 0);
518 }
519 
520 /*
521  * npf_rwrip: rewrite required IP address.
522  */
523 bool
npf_rwrip(const npf_cache_t * npc,u_int which,const npf_addr_t * addr)524 npf_rwrip(const npf_cache_t *npc, u_int which, const npf_addr_t *addr)
525 {
526 	KASSERT(npf_iscached(npc, NPC_IP46));
527 	KASSERT(which == NPF_SRC || which == NPF_DST);
528 
529 	memcpy(npc->npc_ips[which], addr, npc->npc_alen);
530 	return true;
531 }
532 
533 /*
534  * npf_rwrport: rewrite required TCP/UDP port.
535  */
536 bool
npf_rwrport(const npf_cache_t * npc,u_int which,const in_port_t port)537 npf_rwrport(const npf_cache_t *npc, u_int which, const in_port_t port)
538 {
539 	const int proto = npc->npc_proto;
540 	in_port_t *oport;
541 
542 	KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
543 	KASSERT(proto == IPPROTO_TCP || proto == IPPROTO_UDP);
544 	KASSERT(which == NPF_SRC || which == NPF_DST);
545 
546 	/* Get the offset and store the port in it. */
547 	if (proto == IPPROTO_TCP) {
548 		struct tcphdr *th = npc->npc_l4.tcp;
549 		oport = (which == NPF_SRC) ? &th->th_sport : &th->th_dport;
550 	} else {
551 		struct udphdr *uh = npc->npc_l4.udp;
552 		oport = (which == NPF_SRC) ? &uh->uh_sport : &uh->uh_dport;
553 	}
554 	memcpy(oport, &port, sizeof(in_port_t));
555 	return true;
556 }
557 
558 /*
559  * npf_rwrcksum: rewrite IPv4 and/or TCP/UDP checksum.
560  */
561 bool
npf_rwrcksum(const npf_cache_t * npc,u_int which,const npf_addr_t * addr,const in_port_t port)562 npf_rwrcksum(const npf_cache_t *npc, u_int which,
563     const npf_addr_t *addr, const in_port_t port)
564 {
565 	const npf_addr_t *oaddr = npc->npc_ips[which];
566 	const int proto = npc->npc_proto;
567 	const int alen = npc->npc_alen;
568 	uint16_t *ocksum;
569 	in_port_t oport;
570 
571 	KASSERT(npf_iscached(npc, NPC_LAYER4));
572 	KASSERT(which == NPF_SRC || which == NPF_DST);
573 
574 	if (npf_iscached(npc, NPC_IP4)) {
575 		struct ip *ip = npc->npc_ip.v4;
576 		uint16_t ipsum = ip->ip_sum;
577 
578 		/* Recalculate IPv4 checksum and rewrite. */
579 		ip->ip_sum = npf_addr_cksum(ipsum, alen, oaddr, addr);
580 	} else {
581 		/* No checksum for IPv6. */
582 		KASSERT(npf_iscached(npc, NPC_IP6));
583 	}
584 
585 	/* Nothing else to do for ICMP. */
586 	if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) {
587 		return true;
588 	}
589 	KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
590 
591 	/*
592 	 * Calculate TCP/UDP checksum:
593 	 * - Skip if UDP and the current checksum is zero.
594 	 * - Fixup the IP address change.
595 	 * - Fixup the port change, if required (non-zero).
596 	 */
597 	if (proto == IPPROTO_TCP) {
598 		struct tcphdr *th = npc->npc_l4.tcp;
599 
600 		ocksum = &th->th_sum;
601 		oport = (which == NPF_SRC) ? th->th_sport : th->th_dport;
602 	} else {
603 		struct udphdr *uh = npc->npc_l4.udp;
604 
605 		KASSERT(proto == IPPROTO_UDP);
606 		ocksum = &uh->uh_sum;
607 		if (*ocksum == 0) {
608 			/* No need to update. */
609 			return true;
610 		}
611 		oport = (which == NPF_SRC) ? uh->uh_sport : uh->uh_dport;
612 	}
613 
614 	uint16_t cksum = npf_addr_cksum(*ocksum, alen, oaddr, addr);
615 	if (port) {
616 		cksum = npf_fixup16_cksum(cksum, oport, port);
617 	}
618 
619 	/* Rewrite TCP/UDP checksum. */
620 	memcpy(ocksum, &cksum, sizeof(uint16_t));
621 	return true;
622 }
623 
624 /*
625  * npf_napt_rwr: perform address and/or port translation.
626  */
627 int
npf_napt_rwr(const npf_cache_t * npc,u_int which,const npf_addr_t * addr,const in_addr_t port)628 npf_napt_rwr(const npf_cache_t *npc, u_int which,
629     const npf_addr_t *addr, const in_addr_t port)
630 {
631 	const unsigned proto = npc->npc_proto;
632 
633 	/*
634 	 * Rewrite IP and/or TCP/UDP checksums first, since we need the
635 	 * current (old) address/port for the calculations.  Then perform
636 	 * the address translation i.e. rewrite source or destination.
637 	 */
638 	if (!npf_rwrcksum(npc, which, addr, port)) {
639 		return EINVAL;
640 	}
641 	if (!npf_rwrip(npc, which, addr)) {
642 		return EINVAL;
643 	}
644 	if (port == 0) {
645 		/* Done. */
646 		return 0;
647 	}
648 
649 	switch (proto) {
650 	case IPPROTO_TCP:
651 	case IPPROTO_UDP:
652 		/* Rewrite source/destination port. */
653 		if (!npf_rwrport(npc, which, port)) {
654 			return EINVAL;
655 		}
656 		break;
657 	case IPPROTO_ICMP:
658 #ifdef INET6
659 	case IPPROTO_ICMPV6:
660 		KASSERT(npf_iscached(npc, NPC_ICMP));
661 		/* Nothing. */
662 		break;
663 #endif
664 	default:
665 		return ENOTSUP;
666 	}
667 	return 0;
668 }
669 
670 /*
671  * IPv6-to-IPv6 Network Prefix Translation (NPTv6), as per RFC 6296.
672  */
673 
674 #ifdef INET6
675 int
npf_npt66_rwr(const npf_cache_t * npc,u_int which,const npf_addr_t * pref,npf_netmask_t len,uint16_t adj)676 npf_npt66_rwr(const npf_cache_t *npc, u_int which, const npf_addr_t *pref,
677     npf_netmask_t len, uint16_t adj)
678 {
679 	npf_addr_t *addr = npc->npc_ips[which];
680 	unsigned remnant, word, preflen = len >> 4;
681 	uint32_t sum;
682 
683 	KASSERT(which == NPF_SRC || which == NPF_DST);
684 
685 	if (!npf_iscached(npc, NPC_IP6)) {
686 		return EINVAL;
687 	}
688 	if (len <= 48) {
689 		/*
690 		 * The word to adjust.  Cannot translate the 0xffff
691 		 * subnet if /48 or shorter.
692 		 */
693 		word = 3;
694 		if (addr->s6_addr16[word] == 0xffff) {
695 			return EINVAL;
696 		}
697 	} else {
698 		/*
699 		 * Also, all 0s or 1s in the host part are disallowed for
700 		 * longer than /48 prefixes.
701 		 */
702 		if ((addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0) ||
703 		    (addr->s6_addr32[2] == ~0U && addr->s6_addr32[3] == ~0U))
704 			return EINVAL;
705 
706 		/* Determine the 16-bit word to adjust. */
707 		for (word = 4; word < 8; word++)
708 			if (addr->s6_addr16[word] != 0xffff)
709 				break;
710 	}
711 
712 	/* Rewrite the prefix. */
713 	for (unsigned i = 0; i < preflen; i++) {
714 		addr->s6_addr16[i] = pref->s6_addr16[i];
715 	}
716 
717 	/*
718 	 * If prefix length is within a 16-bit word (not dividable by 16),
719 	 * then prepare a mask, determine the word and adjust it.
720 	 */
721 	if ((remnant = len - (preflen << 4)) != 0) {
722 		const uint16_t wordmask = (1U << remnant) - 1;
723 		const unsigned i = preflen;
724 
725 		addr->s6_addr16[i] = (pref->s6_addr16[i] & wordmask) |
726 		    (addr->s6_addr16[i] & ~wordmask);
727 	}
728 
729 	/*
730 	 * Performing 1's complement sum/difference.
731 	 */
732 	sum = addr->s6_addr16[word] + adj;
733 	while (sum >> 16) {
734 		sum = (sum >> 16) + (sum & 0xffff);
735 	}
736 	if (sum == 0xffff) {
737 		/* RFC 1071. */
738 		sum = 0x0000;
739 	}
740 	addr->s6_addr16[word] = sum;
741 	return 0;
742 }
743 #endif
744 
745 #if defined(DDB) || defined(_NPF_TESTING)
746 
747 const char *
npf_addr_dump(const npf_addr_t * addr,int alen)748 npf_addr_dump(const npf_addr_t *addr, int alen)
749 {
750 #ifdef INET6
751 	if (alen == sizeof(struct in_addr)) {
752 #else
753 		KASSERT(alen == sizeof(struct in_addr));
754 #endif
755 		struct in_addr ip;
756 		memcpy(&ip, addr, alen);
757 		return inet_ntoa(ip);
758 #ifdef INET6
759 	}
760 	return ip6_sprintf(addr);
761 #endif
762 }
763 
764 #endif
765