npf_inet.c revision 1.10.4.2 1 /* $NetBSD: npf_inet.c,v 1.10.4.2 2012/06/26 14:49:10 riz Exp $ */
2
3 /*-
4 * Copyright (c) 2009-2012 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 procotol 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.10.4.2 2012/06/26 14:49:10 riz 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 <netinet/in_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: update IPv4 checksum.
65 */
66
67 uint16_t
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 sum = ~ntohs(cksum) & 0xffff;
77 sum += (~ntohs(odatum) & 0xffff) + ntohs(ndatum);
78 sum = (sum >> 16) + (sum & 0xffff);
79 sum += (sum >> 16);
80
81 return htons(~sum & 0xffff);
82 }
83
84 uint16_t
85 npf_fixup32_cksum(uint16_t cksum, uint32_t odatum, uint32_t ndatum)
86 {
87
88 cksum = npf_fixup16_cksum(cksum, odatum & 0xffff, ndatum & 0xffff);
89 cksum = npf_fixup16_cksum(cksum, odatum >> 16, ndatum >> 16);
90 return cksum;
91 }
92
93 /*
94 * npf_addr_cksum: calculate checksum of the address, either IPv4 or IPv6.
95 */
96 uint16_t
97 npf_addr_cksum(uint16_t cksum, int sz, npf_addr_t *oaddr, npf_addr_t *naddr)
98 {
99 uint32_t *oip32 = (uint32_t *)oaddr, *nip32 = (uint32_t *)naddr;
100
101 KASSERT(sz % sizeof(uint32_t) == 0);
102 do {
103 cksum = npf_fixup32_cksum(cksum, *oip32++, *nip32++);
104 sz -= sizeof(uint32_t);
105 } while (sz);
106
107 return cksum;
108 }
109
110 /*
111 * npf_addr_sum: provide IP address as a summed (if needed) 32-bit integer.
112 * Note: used for hash function.
113 */
114 uint32_t
115 npf_addr_sum(const int sz, const npf_addr_t *a1, const npf_addr_t *a2)
116 {
117 uint32_t mix = 0;
118 int i;
119
120 KASSERT(sz > 0 && a1 != NULL && a2 != NULL);
121
122 for (i = 0; i < (sz >> 2); i++) {
123 mix += a1->s6_addr32[i];
124 mix += a2->s6_addr32[i];
125 }
126 return mix;
127 }
128
129 static inline void
130 npf_generate_mask(npf_addr_t *out, const npf_netmask_t mask)
131 {
132 uint_fast8_t length = mask;
133
134 /* Note: maximum length is 32 for IPv4 and 128 for IPv6. */
135 KASSERT(length <= NPF_MAX_NETMASK);
136
137 for (int i = 0; i < 4; i++) {
138 if (length >= 32) {
139 out->s6_addr32[i] = htonl(0xffffffff);
140 length -= 32;
141 } else {
142 out->s6_addr32[i] = htonl(0xffffffff << (32 - length));
143 length = 0;
144 }
145 }
146 }
147
148 /*
149 * npf_addr_mask: apply the mask to a given address and store the result.
150 */
151 void
152 npf_addr_mask(const npf_addr_t *addr, const npf_netmask_t mask, npf_addr_t *out)
153 {
154 npf_addr_t realmask;
155
156 npf_generate_mask(&realmask, mask);
157
158 for (int i = 0; i < 4; i++) {
159 out->s6_addr32[i] = addr->s6_addr32[i] & realmask.s6_addr32[i];
160 }
161 }
162
163 /*
164 * npf_addr_cmp: compare two addresses, either IPv4 or IPv6.
165 *
166 * => Ignore the mask, if NPF_NO_NETMASK is specified.
167 * => Return 0 if equal and -1 or 1 if less or greater accordingly.
168 */
169 int
170 npf_addr_cmp(const npf_addr_t *addr1, const npf_netmask_t mask1,
171 const npf_addr_t *addr2, const npf_netmask_t mask2)
172 {
173 npf_addr_t realmask1, realmask2;
174
175 if (mask1 != NPF_NO_NETMASK) {
176 npf_generate_mask(&realmask1, mask1);
177 }
178 if (mask2 != NPF_NO_NETMASK) {
179 npf_generate_mask(&realmask2, mask2);
180 }
181
182 for (int i = 0; i < 4; i++) {
183 const uint32_t x = mask1 != NPF_NO_NETMASK ?
184 addr1->s6_addr32[i] & realmask1.s6_addr32[i] :
185 addr1->s6_addr32[i];
186 const uint32_t y = mask2 != NPF_NO_NETMASK ?
187 addr2->s6_addr32[i] & realmask2.s6_addr32[i] :
188 addr2->s6_addr32[i];
189 if (x < y) {
190 return -1;
191 }
192 if (x > y) {
193 return 1;
194 }
195 }
196
197 return 0;
198 }
199
200 /*
201 * npf_tcpsaw: helper to fetch SEQ, ACK, WIN and return TCP data length.
202 *
203 * => Returns all values in host byte-order.
204 */
205 int
206 npf_tcpsaw(const npf_cache_t *npc, tcp_seq *seq, tcp_seq *ack, uint32_t *win)
207 {
208 const struct tcphdr *th = &npc->npc_l4.tcp;
209 u_int thlen;
210
211 KASSERT(npf_iscached(npc, NPC_TCP));
212
213 *seq = ntohl(th->th_seq);
214 *ack = ntohl(th->th_ack);
215 *win = (uint32_t)ntohs(th->th_win);
216 thlen = th->th_off << 2;
217
218 if (npf_iscached(npc, NPC_IP4)) {
219 const struct ip *ip = &npc->npc_ip.v4;
220 return ntohs(ip->ip_len) - npf_cache_hlen(npc) - thlen;
221 } else if (npf_iscached(npc, NPC_IP6)) {
222 const struct ip6_hdr *ip6 = &npc->npc_ip.v6;
223 return ntohs(ip6->ip6_plen) - thlen;
224 }
225 return 0;
226 }
227
228 /*
229 * npf_fetch_tcpopts: parse and return TCP options.
230 */
231 bool
232 npf_fetch_tcpopts(const npf_cache_t *npc, nbuf_t *nbuf,
233 uint16_t *mss, int *wscale)
234 {
235 void *n_ptr = nbuf_dataptr(nbuf);
236 const struct tcphdr *th = &npc->npc_l4.tcp;
237 int topts_len, step;
238 uint16_t val16;
239 uint8_t val;
240
241 KASSERT(npf_iscached(npc, NPC_IP46));
242 KASSERT(npf_iscached(npc, NPC_TCP));
243
244 /* Determine if there are any TCP options, get their length. */
245 topts_len = (th->th_off << 2) - sizeof(struct tcphdr);
246 if (topts_len <= 0) {
247 /* No options. */
248 return false;
249 }
250 KASSERT(topts_len <= MAX_TCPOPTLEN);
251
252 /* First step: IP and TCP header up to options. */
253 step = npf_cache_hlen(npc) + sizeof(struct tcphdr);
254 next:
255 if (nbuf_advfetch(&nbuf, &n_ptr, step, sizeof(val), &val)) {
256 return false;
257 }
258
259 switch (val) {
260 case TCPOPT_EOL:
261 /* Done. */
262 return true;
263 case TCPOPT_NOP:
264 topts_len--;
265 step = 1;
266 break;
267 case TCPOPT_MAXSEG:
268 /*
269 * XXX: clean this mess.
270 */
271 if (mss && *mss) {
272 val16 = *mss;
273 if (nbuf_advstore(&nbuf, &n_ptr, 2,
274 sizeof(val16), &val16))
275 return false;
276 } else if (nbuf_advfetch(&nbuf, &n_ptr, 2,
277 sizeof(val16), &val16)) {
278 return false;
279 }
280 if (mss) {
281 *mss = val16;
282 }
283 topts_len -= TCPOLEN_MAXSEG;
284 step = sizeof(val16);
285 break;
286 case TCPOPT_WINDOW:
287 /* TCP Window Scaling (RFC 1323). */
288 if (nbuf_advfetch(&nbuf, &n_ptr, 2, sizeof(val), &val)) {
289 return false;
290 }
291 *wscale = (val > TCP_MAX_WINSHIFT) ? TCP_MAX_WINSHIFT : val;
292 topts_len -= TCPOLEN_WINDOW;
293 step = sizeof(val);
294 break;
295 default:
296 if (nbuf_advfetch(&nbuf, &n_ptr, 1, sizeof(val), &val)) {
297 return false;
298 }
299 if (val < 2 || val >= topts_len) {
300 return false;
301 }
302 topts_len -= val;
303 step = val - 1;
304 }
305
306 /* Any options left? */
307 if (__predict_true(topts_len > 0)) {
308 goto next;
309 }
310 return true;
311 }
312
313 /*
314 * npf_fetch_ip: fetch, check and cache IP header.
315 */
316 bool
317 npf_fetch_ip(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
318 {
319 uint8_t ver;
320
321 if (nbuf_fetch_datum(nbuf, n_ptr, sizeof(uint8_t), &ver)) {
322 return false;
323 }
324
325 switch (ver >> 4) {
326 case IPVERSION: {
327 struct ip *ip = &npc->npc_ip.v4;
328
329 /* Fetch IPv4 header. */
330 if (nbuf_fetch_datum(nbuf, n_ptr, sizeof(struct ip), ip)) {
331 return false;
332 }
333
334 /* Check header length and fragment offset. */
335 if ((u_int)(ip->ip_hl << 2) < sizeof(struct ip)) {
336 return false;
337 }
338 if (ip->ip_off & ~htons(IP_DF | IP_RF)) {
339 /* Note fragmentation. */
340 npc->npc_info |= NPC_IPFRAG;
341 }
342
343 /* Cache: layer 3 - IPv4. */
344 npc->npc_ipsz = sizeof(struct in_addr);
345 npc->npc_srcip = (npf_addr_t *)&ip->ip_src;
346 npc->npc_dstip = (npf_addr_t *)&ip->ip_dst;
347 npc->npc_info |= NPC_IP4;
348 npc->npc_hlen = ip->ip_hl << 2;
349 npc->npc_next_proto = npc->npc_ip.v4.ip_p;
350 break;
351 }
352
353 case (IPV6_VERSION >> 4): {
354 struct ip6_hdr *ip6 = &npc->npc_ip.v6;
355 size_t toskip;
356 bool done;
357
358 /* Fetch IPv6 header. */
359 if (nbuf_fetch_datum(nbuf, n_ptr, sizeof(struct ip6_hdr), ip6)) {
360 return false;
361 }
362
363 /* Initial next-protocol value. */
364 npc->npc_next_proto = ip6->ip6_nxt;
365 toskip = sizeof(struct ip6_hdr);
366 npc->npc_hlen = 0;
367 done = false;
368
369 /*
370 * Advance by the length of the previous known header and
371 * fetch by the lengh of next extension header.
372 */
373 do {
374 struct ip6_ext ip6e;
375
376 if (nbuf_advfetch(&nbuf, &n_ptr, toskip,
377 sizeof(struct ip6_ext), &ip6e)) {
378 return false;
379 }
380 switch (npc->npc_next_proto) {
381 case IPPROTO_DSTOPTS:
382 case IPPROTO_ROUTING:
383 toskip = (ip6e.ip6e_len + 1) << 3;
384 break;
385 case IPPROTO_FRAGMENT:
386 npc->npc_info |= NPC_IPFRAG;
387 toskip = sizeof(struct ip6_frag);
388 break;
389 case IPPROTO_AH:
390 toskip = (ip6e.ip6e_len + 2) << 2;
391 break;
392 default:
393 done = true;
394 break;
395 }
396 npc->npc_hlen += toskip;
397 npc->npc_next_proto = ip6e.ip6e_nxt;
398
399 } while (!done);
400
401 /* Cache: layer 3 - IPv6. */
402 npc->npc_ipsz = sizeof(struct in6_addr);
403 npc->npc_srcip = (npf_addr_t *)&ip6->ip6_src;
404 npc->npc_dstip = (npf_addr_t *)&ip6->ip6_dst;
405 npc->npc_info |= NPC_IP6;
406 break;
407 }
408 default:
409 return false;
410 }
411
412 return true;
413 }
414
415 /*
416 * npf_fetch_tcp: fetch, check and cache TCP header. If necessary,
417 * fetch and cache layer 3 as well.
418 */
419 bool
420 npf_fetch_tcp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
421 {
422 struct tcphdr *th;
423
424 /* Must have IP header processed for its length and protocol. */
425 if (!npf_iscached(npc, NPC_IP46) && !npf_fetch_ip(npc, nbuf, n_ptr)) {
426 return false;
427 }
428 if (npf_cache_ipproto(npc) != IPPROTO_TCP) {
429 return false;
430 }
431 th = &npc->npc_l4.tcp;
432
433 /* Fetch TCP header. */
434 if (nbuf_advfetch(&nbuf, &n_ptr, npf_cache_hlen(npc),
435 sizeof(struct tcphdr), th)) {
436 return false;
437 }
438
439 /* Cache: layer 4 - TCP. */
440 npc->npc_info |= (NPC_LAYER4 | NPC_TCP);
441 return true;
442 }
443
444 /*
445 * npf_fetch_udp: fetch, check and cache UDP header. If necessary,
446 * fetch and cache layer 3 as well.
447 */
448 bool
449 npf_fetch_udp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
450 {
451 struct ip *ip = &npc->npc_ip.v4;
452 struct udphdr *uh;
453 u_int hlen;
454
455 /* Must have IP header processed for its length and protocol. */
456 if (!npf_iscached(npc, NPC_IP46) && !npf_fetch_ip(npc, nbuf, n_ptr)) {
457 return false;
458 }
459 if (ip->ip_p != IPPROTO_UDP) {
460 return false;
461 }
462 uh = &npc->npc_l4.udp;
463 hlen = npf_cache_hlen(npc);
464
465 /* Fetch UDP header. */
466 if (nbuf_advfetch(&nbuf, &n_ptr, hlen, sizeof(struct udphdr), uh)) {
467 return false;
468 }
469
470 /* Cache: layer 4 - UDP. */
471 npc->npc_info |= (NPC_LAYER4 | NPC_UDP);
472 return true;
473 }
474
475 /*
476 * npf_fetch_icmp: fetch ICMP code, type and possible query ID.
477 */
478 bool
479 npf_fetch_icmp(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr)
480 {
481 struct ip *ip = &npc->npc_ip.v4;
482 struct icmp *ic;
483 u_int hlen, iclen;
484
485 /* Must have IP header processed for its length and protocol. */
486 if (!npf_iscached(npc, NPC_IP46) && !npf_fetch_ip(npc, nbuf, n_ptr)) {
487 return false;
488 }
489 if (ip->ip_p != IPPROTO_ICMP) {
490 return false;
491 }
492 ic = &npc->npc_l4.icmp;
493 hlen = npf_cache_hlen(npc);
494
495 /* Fetch basic ICMP header, up to the "data" point. */
496 iclen = offsetof(struct icmp, icmp_data);
497 if (nbuf_advfetch(&nbuf, &n_ptr, hlen, iclen, ic)) {
498 return false;
499 }
500
501 /* Cache: layer 4 - ICMP. */
502 npc->npc_info |= (NPC_LAYER4 | NPC_ICMP);
503 return true;
504 }
505
506 /*
507 * npf_cache_all: general routine to cache all relevant IP (v4 or v6)
508 * and TCP, UDP or ICMP headers.
509 */
510 int
511 npf_cache_all(npf_cache_t *npc, nbuf_t *nbuf)
512 {
513 void *n_ptr = nbuf_dataptr(nbuf);
514
515 if (!npf_iscached(npc, NPC_IP46) && !npf_fetch_ip(npc, nbuf, n_ptr)) {
516 return npc->npc_info;
517 }
518 if (npf_iscached(npc, NPC_IPFRAG)) {
519 return npc->npc_info;
520 }
521 switch (npf_cache_ipproto(npc)) {
522 case IPPROTO_TCP:
523 (void)npf_fetch_tcp(npc, nbuf, n_ptr);
524 break;
525 case IPPROTO_UDP:
526 (void)npf_fetch_udp(npc, nbuf, n_ptr);
527 break;
528 case IPPROTO_ICMP:
529 (void)npf_fetch_icmp(npc, nbuf, n_ptr);
530 break;
531 }
532 return npc->npc_info;
533 }
534
535 /*
536 * npf_rwrip: rewrite required IP address, update the cache.
537 */
538 bool
539 npf_rwrip(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr, const int di,
540 npf_addr_t *addr)
541 {
542 npf_addr_t *oaddr;
543 u_int offby;
544
545 KASSERT(npf_iscached(npc, NPC_IP46));
546
547 if (di == PFIL_OUT) {
548 /* Rewrite source address, if outgoing. */
549 offby = offsetof(struct ip, ip_src);
550 oaddr = npc->npc_srcip;
551 } else {
552 /* Rewrite destination, if incoming. */
553 offby = offsetof(struct ip, ip_dst);
554 oaddr = npc->npc_dstip;
555 }
556
557 /* Advance to the address and rewrite it. */
558 if (nbuf_advstore(&nbuf, &n_ptr, offby, npc->npc_ipsz, addr))
559 return false;
560
561 /* Cache: IP address. */
562 memcpy(oaddr, addr, npc->npc_ipsz);
563 return true;
564 }
565
566 /*
567 * npf_rwrport: rewrite required TCP/UDP port, update the cache.
568 */
569 bool
570 npf_rwrport(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr, const int di,
571 in_port_t port)
572 {
573 const int proto = npf_cache_ipproto(npc);
574 u_int offby = npf_cache_hlen(npc);
575 in_port_t *oport;
576
577 KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
578 KASSERT(proto == IPPROTO_TCP || proto == IPPROTO_UDP);
579
580 /* Offset to the port and pointer in the cache. */
581 if (proto == IPPROTO_TCP) {
582 struct tcphdr *th = &npc->npc_l4.tcp;
583 if (di == PFIL_OUT) {
584 CTASSERT(offsetof(struct tcphdr, th_sport) == 0);
585 oport = &th->th_sport;
586 } else {
587 offby += offsetof(struct tcphdr, th_dport);
588 oport = &th->th_dport;
589 }
590 } else {
591 struct udphdr *uh = &npc->npc_l4.udp;
592 if (di == PFIL_OUT) {
593 CTASSERT(offsetof(struct udphdr, uh_sport) == 0);
594 oport = &uh->uh_sport;
595 } else {
596 offby += offsetof(struct udphdr, uh_dport);
597 oport = &uh->uh_dport;
598 }
599 }
600
601 /* Advance and rewrite the port. */
602 if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(in_port_t), &port))
603 return false;
604
605 /* Cache: TCP/UDP port. */
606 *oport = port;
607 return true;
608 }
609
610 /*
611 * npf_rwrcksum: rewrite IPv4 and/or TCP/UDP checksum, update the cache.
612 */
613 bool
614 npf_rwrcksum(npf_cache_t *npc, nbuf_t *nbuf, void *n_ptr, const int di,
615 npf_addr_t *addr, in_port_t port)
616 {
617 const int proto = npf_cache_ipproto(npc);
618 npf_addr_t *oaddr;
619 in_port_t *oport;
620 uint16_t *cksum;
621 u_int offby;
622
623 /* Checksum update for IPv4 header. */
624 if (npf_iscached(npc, NPC_IP4)) {
625 struct ip *ip = &npc->npc_ip.v4;
626 uint16_t ipsum;
627
628 oaddr = (di == PFIL_OUT) ? npc->npc_srcip : npc->npc_dstip;
629 ipsum = npf_addr_cksum(ip->ip_sum, npc->npc_ipsz, oaddr, addr);
630
631 /* Advance to the IPv4 checksum and rewrite it. */
632 offby = offsetof(struct ip, ip_sum);
633 if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(ipsum), &ipsum))
634 return false;
635
636 ip->ip_sum = ipsum;
637 offby = npf_cache_hlen(npc) - offby;
638 } else {
639 /* No checksum for IPv6. */
640 KASSERT(npf_iscached(npc, NPC_IP6));
641 oaddr = NULL;
642 offby = 0;
643 return false; /* XXX: Not yet supported. */
644 }
645
646 /* Determine whether TCP/UDP checksum update is needed. */
647 if (proto == IPPROTO_ICMP || port == 0) {
648 return true;
649 }
650 KASSERT(npf_iscached(npc, NPC_TCP) || npf_iscached(npc, NPC_UDP));
651
652 /* Calculate TCP/UDP checksum. */
653 if (proto == IPPROTO_TCP) {
654 struct tcphdr *th = &npc->npc_l4.tcp;
655
656 cksum = &th->th_sum;
657 offby += offsetof(struct tcphdr, th_sum);
658 oport = (di == PFIL_OUT) ? &th->th_sport : &th->th_dport;
659 } else {
660 struct udphdr *uh = &npc->npc_l4.udp;
661
662 KASSERT(proto == IPPROTO_UDP);
663 cksum = &uh->uh_sum;
664 if (*cksum == 0) {
665 /* No need to update. */
666 return true;
667 }
668 offby += offsetof(struct udphdr, uh_sum);
669 oport = (di == PFIL_OUT) ? &uh->uh_sport : &uh->uh_dport;
670 }
671 *cksum = npf_addr_cksum(*cksum, npc->npc_ipsz, oaddr, addr);
672 *cksum = npf_fixup16_cksum(*cksum, *oport, port);
673
674 /* Advance to TCP/UDP checksum and rewrite it. */
675 if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(uint16_t), cksum)) {
676 return false;
677 }
678 return true;
679 }
680
681 static inline bool
682 npf_normalize_ip4(npf_cache_t *npc, nbuf_t *nbuf,
683 bool rnd, bool no_df, int minttl)
684 {
685 void *n_ptr = nbuf_dataptr(nbuf);
686 struct ip *ip = &npc->npc_ip.v4;
687 uint16_t cksum = ip->ip_sum;
688 uint16_t ip_off = ip->ip_off;
689 uint8_t ttl = ip->ip_ttl;
690 u_int offby = 0;
691
692 KASSERT(rnd || minttl || no_df);
693
694 /* Randomize IPv4 ID. */
695 if (rnd) {
696 uint16_t oid = ip->ip_id, nid;
697
698 nid = htons(ip_randomid(ip_ids, 0));
699 offby = offsetof(struct ip, ip_id);
700 if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(nid), &nid)) {
701 return false;
702 }
703 cksum = npf_fixup16_cksum(cksum, oid, nid);
704 ip->ip_id = nid;
705 }
706
707 /* IP_DF flag cleansing. */
708 if (no_df && (ip_off & htons(IP_DF)) != 0) {
709 uint16_t nip_off = ip_off & ~htons(IP_DF);
710
711 if (nbuf_advstore(&nbuf, &n_ptr,
712 offsetof(struct ip, ip_off) - offby,
713 sizeof(uint16_t), &nip_off)) {
714 return false;
715 }
716 cksum = npf_fixup16_cksum(cksum, ip_off, nip_off);
717 ip->ip_off = nip_off;
718 offby = offsetof(struct ip, ip_off);
719 }
720
721 /* Enforce minimum TTL. */
722 if (minttl && ttl < minttl) {
723 if (nbuf_advstore(&nbuf, &n_ptr,
724 offsetof(struct ip, ip_ttl) - offby,
725 sizeof(uint8_t), &minttl)) {
726 return false;
727 }
728 cksum = npf_fixup16_cksum(cksum, ttl, minttl);
729 ip->ip_ttl = minttl;
730 offby = offsetof(struct ip, ip_ttl);
731 }
732
733 /* Update IP checksum. */
734 offby = offsetof(struct ip, ip_sum) - offby;
735 if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(cksum), &cksum)) {
736 return false;
737 }
738 ip->ip_sum = cksum;
739 return true;
740 }
741
742 bool
743 npf_normalize(npf_cache_t *npc, nbuf_t *nbuf,
744 bool no_df, bool rnd, u_int minttl, u_int maxmss)
745 {
746 void *n_ptr = nbuf_dataptr(nbuf);
747 struct tcphdr *th = &npc->npc_l4.tcp;
748 uint16_t cksum, mss;
749 u_int offby;
750 int wscale;
751
752 /* Normalize IPv4. */
753 if (npf_iscached(npc, NPC_IP4) && (rnd || minttl)) {
754 if (!npf_normalize_ip4(npc, nbuf, rnd, no_df, minttl)) {
755 return false;
756 }
757 } else if (!npf_iscached(npc, NPC_IP4)) {
758 /* XXX: no IPv6 */
759 return false;
760 }
761
762 /*
763 * TCP Maximum Segment Size (MSS) "clamping". Only if SYN packet.
764 * Fetch MSS and check whether rewrite to lower is needed.
765 */
766 if (maxmss == 0 || !npf_iscached(npc, NPC_TCP) ||
767 (th->th_flags & TH_SYN) == 0) {
768 /* Not required; done. */
769 return true;
770 }
771 mss = 0;
772 if (!npf_fetch_tcpopts(npc, nbuf, &mss, &wscale)) {
773 return false;
774 }
775 if (ntohs(mss) <= maxmss) {
776 return true;
777 }
778
779 /* Calculate TCP checksum, then rewrite MSS and the checksum. */
780 maxmss = htons(maxmss);
781 cksum = npf_fixup16_cksum(th->th_sum, mss, maxmss);
782 th->th_sum = cksum;
783 mss = maxmss;
784 if (!npf_fetch_tcpopts(npc, nbuf, &mss, &wscale)) {
785 return false;
786 }
787 offby = npf_cache_hlen(npc) + offsetof(struct tcphdr, th_sum);
788 if (nbuf_advstore(&nbuf, &n_ptr, offby, sizeof(cksum), &cksum)) {
789 return false;
790 }
791 return true;
792 }
793