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