1 /* $NetBSD: npf_inet.c,v 1.33 2015/12/17 12:17:13 mlelstv 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.33 2015/12/17 12:17:13 mlelstv 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 case IPPROTO_ICMPV6: 659 KASSERT(npf_iscached(npc, NPC_ICMP)); 660 /* Nothing. */ 661 break; 662 default: 663 return ENOTSUP; 664 } 665 return 0; 666 } 667 668 /* 669 * IPv6-to-IPv6 Network Prefix Translation (NPTv6), as per RFC 6296. 670 */ 671 672 int 673 npf_npt66_rwr(const npf_cache_t *npc, u_int which, const npf_addr_t *pref, 674 npf_netmask_t len, uint16_t adj) 675 { 676 npf_addr_t *addr = npc->npc_ips[which]; 677 unsigned remnant, word, preflen = len >> 4; 678 uint32_t sum; 679 680 KASSERT(which == NPF_SRC || which == NPF_DST); 681 682 if (!npf_iscached(npc, NPC_IP6)) { 683 return EINVAL; 684 } 685 if (len <= 48) { 686 /* 687 * The word to adjust. Cannot translate the 0xffff 688 * subnet if /48 or shorter. 689 */ 690 word = 3; 691 if (addr->s6_addr16[word] == 0xffff) { 692 return EINVAL; 693 } 694 } else { 695 /* 696 * Also, all 0s or 1s in the host part are disallowed for 697 * longer than /48 prefixes. 698 */ 699 if ((addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0) || 700 (addr->s6_addr32[2] == ~0U && addr->s6_addr32[3] == ~0U)) 701 return EINVAL; 702 703 /* Determine the 16-bit word to adjust. */ 704 for (word = 4; word < 8; word++) 705 if (addr->s6_addr16[word] != 0xffff) 706 break; 707 } 708 709 /* Rewrite the prefix. */ 710 for (unsigned i = 0; i < preflen; i++) { 711 addr->s6_addr16[i] = pref->s6_addr16[i]; 712 } 713 714 /* 715 * If prefix length is within a 16-bit word (not dividable by 16), 716 * then prepare a mask, determine the word and adjust it. 717 */ 718 if ((remnant = len - (preflen << 4)) != 0) { 719 const uint16_t wordmask = (1U << remnant) - 1; 720 const unsigned i = preflen; 721 722 addr->s6_addr16[i] = (pref->s6_addr16[i] & wordmask) | 723 (addr->s6_addr16[i] & ~wordmask); 724 } 725 726 /* 727 * Performing 1's complement sum/difference. 728 */ 729 sum = addr->s6_addr16[word] + adj; 730 while (sum >> 16) { 731 sum = (sum >> 16) + (sum & 0xffff); 732 } 733 if (sum == 0xffff) { 734 /* RFC 1071. */ 735 sum = 0x0000; 736 } 737 addr->s6_addr16[word] = sum; 738 return 0; 739 } 740 741 #if defined(DDB) || defined(_NPF_TESTING) 742 743 const char * 744 npf_addr_dump(const npf_addr_t *addr, int alen) 745 { 746 if (alen == sizeof(struct in_addr)) { 747 struct in_addr ip; 748 memcpy(&ip, addr, alen); 749 return inet_ntoa(ip); 750 } 751 return ip6_sprintf(addr); 752 } 753 754 #endif 755