version 1.34, 2016/03/18 10:09:46 |
version 1.34.2.2, 2017/03/20 06:57:50 |
|
|
* on rewrites (e.g. by translation routines). |
* on rewrites (e.g. by translation routines). |
*/ |
*/ |
|
|
|
#ifdef _KERNEL |
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
__KERNEL_RCSID(0, "$NetBSD$"); |
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
Line 57 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 58 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <netinet/tcp.h> |
#include <netinet/tcp.h> |
#include <netinet/udp.h> |
#include <netinet/udp.h> |
#include <netinet/ip_icmp.h> |
#include <netinet/ip_icmp.h> |
|
#endif |
|
|
#include "npf_impl.h" |
#include "npf_impl.h" |
|
|
Line 132 npf_addr_mix(const int sz, const npf_add |
|
Line 134 npf_addr_mix(const int sz, const npf_add |
|
KASSERT(sz > 0 && a1 != NULL && a2 != NULL); |
KASSERT(sz > 0 && a1 != NULL && a2 != NULL); |
|
|
for (int i = 0; i < (sz >> 2); i++) { |
for (int i = 0; i < (sz >> 2); i++) { |
mix ^= a1->s6_addr32[i]; |
mix ^= a1->word32[i]; |
mix ^= a2->s6_addr32[i]; |
mix ^= a2->word32[i]; |
} |
} |
return mix; |
return mix; |
} |
} |
Line 163 npf_addr_mask(const npf_addr_t *addr, co |
|
Line 165 npf_addr_mask(const npf_addr_t *addr, co |
|
} else { |
} else { |
wordmask = 0; |
wordmask = 0; |
} |
} |
out->s6_addr32[i] = addr->s6_addr32[i] & wordmask; |
out->word32[i] = addr->word32[i] & wordmask; |
} |
} |
} |
} |
|
|
Line 353 npf_cache_ip(npf_cache_t *npc, nbuf_t *n |
|
Line 355 npf_cache_ip(npf_cache_t *npc, nbuf_t *n |
|
case (IPV6_VERSION >> 4): { |
case (IPV6_VERSION >> 4): { |
struct ip6_hdr *ip6; |
struct ip6_hdr *ip6; |
struct ip6_ext *ip6e; |
struct ip6_ext *ip6e; |
|
struct ip6_frag *ip6f; |
size_t off, hlen; |
size_t off, hlen; |
|
|
ip6 = nbuf_ensure_contig(nbuf, sizeof(struct ip6_hdr)); |
ip6 = nbuf_ensure_contig(nbuf, sizeof(struct ip6_hdr)); |
Line 385 npf_cache_ip(npf_cache_t *npc, nbuf_t *n |
|
Line 388 npf_cache_ip(npf_cache_t *npc, nbuf_t *n |
|
hlen = (ip6e->ip6e_len + 1) << 3; |
hlen = (ip6e->ip6e_len + 1) << 3; |
break; |
break; |
case IPPROTO_FRAGMENT: |
case IPPROTO_FRAGMENT: |
|
ip6f = nbuf_ensure_contig(nbuf, sizeof(*ip6f)); |
|
if (ip6f == NULL) |
|
return 0; |
|
/* |
|
* We treat the first fragment as a regular |
|
* packet and then we pass the rest of the |
|
* fragments unconditionally. This way if |
|
* the first packet passes the rest will |
|
* be able to reassembled, if not they will |
|
* be ignored. We can do better later. |
|
*/ |
|
if (ntohs(ip6f->ip6f_offlg & IP6F_OFF_MASK) != 0) |
|
flags |= NPC_IPFRAG; |
|
|
hlen = sizeof(struct ip6_frag); |
hlen = sizeof(struct ip6_frag); |
flags |= NPC_IPFRAG; |
|
break; |
break; |
case IPPROTO_AH: |
case IPPROTO_AH: |
hlen = (ip6e->ip6e_len + 2) << 2; |
hlen = (ip6e->ip6e_len + 2) << 2; |
Line 655 npf_napt_rwr(const npf_cache_t *npc, u_i |
|
Line 671 npf_napt_rwr(const npf_cache_t *npc, u_i |
|
} |
} |
break; |
break; |
case IPPROTO_ICMP: |
case IPPROTO_ICMP: |
#ifdef INET6 |
|
case IPPROTO_ICMPV6: |
case IPPROTO_ICMPV6: |
KASSERT(npf_iscached(npc, NPC_ICMP)); |
KASSERT(npf_iscached(npc, NPC_ICMP)); |
/* Nothing. */ |
/* Nothing. */ |
break; |
break; |
#endif |
|
default: |
default: |
return ENOTSUP; |
return ENOTSUP; |
} |
} |
Line 671 npf_napt_rwr(const npf_cache_t *npc, u_i |
|
Line 685 npf_napt_rwr(const npf_cache_t *npc, u_i |
|
* IPv6-to-IPv6 Network Prefix Translation (NPTv6), as per RFC 6296. |
* IPv6-to-IPv6 Network Prefix Translation (NPTv6), as per RFC 6296. |
*/ |
*/ |
|
|
#ifdef INET6 |
|
int |
int |
npf_npt66_rwr(const npf_cache_t *npc, u_int which, const npf_addr_t *pref, |
npf_npt66_rwr(const npf_cache_t *npc, u_int which, const npf_addr_t *pref, |
npf_netmask_t len, uint16_t adj) |
npf_netmask_t len, uint16_t adj) |
Line 691 npf_npt66_rwr(const npf_cache_t *npc, u_ |
|
Line 704 npf_npt66_rwr(const npf_cache_t *npc, u_ |
|
* subnet if /48 or shorter. |
* subnet if /48 or shorter. |
*/ |
*/ |
word = 3; |
word = 3; |
if (addr->s6_addr16[word] == 0xffff) { |
if (addr->word16[word] == 0xffff) { |
return EINVAL; |
return EINVAL; |
} |
} |
} else { |
} else { |
Line 699 npf_npt66_rwr(const npf_cache_t *npc, u_ |
|
Line 712 npf_npt66_rwr(const npf_cache_t *npc, u_ |
|
* Also, all 0s or 1s in the host part are disallowed for |
* Also, all 0s or 1s in the host part are disallowed for |
* longer than /48 prefixes. |
* longer than /48 prefixes. |
*/ |
*/ |
if ((addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0) || |
if ((addr->word32[2] == 0 && addr->word32[3] == 0) || |
(addr->s6_addr32[2] == ~0U && addr->s6_addr32[3] == ~0U)) |
(addr->word32[2] == ~0U && addr->word32[3] == ~0U)) |
return EINVAL; |
return EINVAL; |
|
|
/* Determine the 16-bit word to adjust. */ |
/* Determine the 16-bit word to adjust. */ |
for (word = 4; word < 8; word++) |
for (word = 4; word < 8; word++) |
if (addr->s6_addr16[word] != 0xffff) |
if (addr->word16[word] != 0xffff) |
break; |
break; |
} |
} |
|
|
/* Rewrite the prefix. */ |
/* Rewrite the prefix. */ |
for (unsigned i = 0; i < preflen; i++) { |
for (unsigned i = 0; i < preflen; i++) { |
addr->s6_addr16[i] = pref->s6_addr16[i]; |
addr->word16[i] = pref->word16[i]; |
} |
} |
|
|
/* |
/* |
Line 722 npf_npt66_rwr(const npf_cache_t *npc, u_ |
|
Line 735 npf_npt66_rwr(const npf_cache_t *npc, u_ |
|
const uint16_t wordmask = (1U << remnant) - 1; |
const uint16_t wordmask = (1U << remnant) - 1; |
const unsigned i = preflen; |
const unsigned i = preflen; |
|
|
addr->s6_addr16[i] = (pref->s6_addr16[i] & wordmask) | |
addr->word16[i] = (pref->word16[i] & wordmask) | |
(addr->s6_addr16[i] & ~wordmask); |
(addr->word16[i] & ~wordmask); |
} |
} |
|
|
/* |
/* |
* Performing 1's complement sum/difference. |
* Performing 1's complement sum/difference. |
*/ |
*/ |
sum = addr->s6_addr16[word] + adj; |
sum = addr->word16[word] + adj; |
while (sum >> 16) { |
while (sum >> 16) { |
sum = (sum >> 16) + (sum & 0xffff); |
sum = (sum >> 16) + (sum & 0xffff); |
} |
} |
Line 737 npf_npt66_rwr(const npf_cache_t *npc, u_ |
|
Line 750 npf_npt66_rwr(const npf_cache_t *npc, u_ |
|
/* RFC 1071. */ |
/* RFC 1071. */ |
sum = 0x0000; |
sum = 0x0000; |
} |
} |
addr->s6_addr16[word] = sum; |
addr->word16[word] = sum; |
return 0; |
return 0; |
} |
} |
#endif |
|
|
|
#if defined(DDB) || defined(_NPF_TESTING) |
#if defined(DDB) || defined(_NPF_TESTING) |
|
|
const char * |
const char * |
npf_addr_dump(const npf_addr_t *addr, int alen) |
npf_addr_dump(const npf_addr_t *addr, int alen) |
{ |
{ |
#ifdef INET6 |
|
if (alen == sizeof(struct in_addr)) { |
if (alen == sizeof(struct in_addr)) { |
#else |
|
KASSERT(alen == sizeof(struct in_addr)); |
|
#endif |
|
struct in_addr ip; |
struct in_addr ip; |
memcpy(&ip, addr, alen); |
memcpy(&ip, addr, alen); |
return inet_ntoa(ip); |
return inet_ntoa(ip); |
#ifdef INET6 |
|
} |
} |
return ip6_sprintf(addr); |
return "[IPv6]"; |
#endif |
|
} |
} |
|
|
#endif |
#endif |