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