Index: sbin/ipfw/ipfw.8 =================================================================== --- sbin/ipfw/ipfw.8 +++ sbin/ipfw/ipfw.8 @@ -3556,6 +3556,10 @@ The IPv6 prefix defines IPv4-embedded IPv6 addresses used by translator to represent destination IPv4 addresses. This IPv6 prefix should be configured on a remote NAT64 translator. +.It Cm local +Create UE (client) instance for packets originating from the local node. +.It Cm -local +Create CPE (router) instance for packets originating from the CPE network. .It Cm log Turn on logging of all handled packets via BPF through .Ar ipfwlog0 Index: sbin/ipfw/ipfw2.h =================================================================== --- sbin/ipfw/ipfw2.h +++ sbin/ipfw/ipfw2.h @@ -300,6 +300,8 @@ TOK_NAT64CLAT, TOK_PLAT_PREFIX, TOK_CLAT_PREFIX, + TOK_CLAT_LOCAL, + TOK_CLAT_LOCALOFF, /* NPTv6 tokens */ TOK_NPTV6, Index: sbin/ipfw/nat64clat.c =================================================================== --- sbin/ipfw/nat64clat.c +++ sbin/ipfw/nat64clat.c @@ -162,6 +162,8 @@ static struct _s_x nat64newcmds[] = { { "plat_prefix", TOK_PLAT_PREFIX }, { "clat_prefix", TOK_CLAT_PREFIX }, + { "local", TOK_CLAT_LOCAL }, + { "-local", TOK_CLAT_LOCALOFF }, { "log", TOK_LOG }, { "-log", TOK_LOGOFF }, { "allow_private", TOK_PRIVATE }, @@ -193,6 +195,7 @@ /* Some reasonable defaults */ inet_pton(AF_INET6, "64:ff9b::", &cfg->plat_prefix); + cfg->clat_local = 0; cfg->plat_plen = 96; cfg->set = set; flags = NAT64CLAT_HAS_PLAT_PREFIX; @@ -229,6 +232,12 @@ } ac--; av++; break; + case TOK_CLAT_LOCAL: + cfg->clat_local = 1; + break; + case TOK_CLAT_LOCALOFF: + cfg->clat_local = 0; + break; case TOK_LOG: cfg->flags |= NAT64_LOG; break; @@ -448,6 +457,8 @@ inet_ntop(AF_INET6, &cfg->plat_prefix, plat_buf, sizeof(plat_buf)); printf("nat64clat %s clat_prefix %s/%u plat_prefix %s/%u", cfg->name, clat_buf, cfg->clat_plen, plat_buf, cfg->plat_plen); + if ((cfg->clat_local) != 0) + printf(" local"); if (cfg->flags & NAT64_LOG) printf(" log"); if (cfg->flags & NAT64_ALLOW_PRIVATE) Index: sys/netinet6/ip_fw_nat64.h =================================================================== --- sys/netinet6/ip_fw_nat64.h +++ sys/netinet6/ip_fw_nat64.h @@ -114,6 +114,7 @@ struct in6_addr clat_prefix; /* Client (CLAT) prefix */ uint8_t plat_plen; /* PLAT Prefix length */ uint8_t clat_plen; /* CLAT Prefix length */ + uint8_t clat_local; /* CLAT UE parameter */ uint8_t set; /* Named instance set [0..31] */ uint8_t spare; uint32_t flags; Index: sys/netpfil/ipfw/nat64/nat64_translate.h =================================================================== --- sys/netpfil/ipfw/nat64/nat64_translate.h +++ sys/netpfil/ipfw/nat64/nat64_translate.h @@ -142,7 +142,7 @@ int nat64_getlasthdr(struct mbuf *m, int *offset); int nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *saddr, struct in6_addr *daddr, uint16_t lport, struct nat64_config *cfg, - void *logdata); + uint8_t nat64_local, void *logdata); int nat64_do_handle_ip6(struct mbuf *m, uint32_t aaddr, uint16_t aport, struct nat64_config *cfg, void *logdata); int nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t aaddr, @@ -149,6 +149,7 @@ uint16_t aport, struct nat64_config *cfg, void *logdata); void nat64_embed_ip4(struct in6_addr *ip6, int plen, in_addr_t ia); in_addr_t nat64_extract_ip4(const struct in6_addr *ip6, int plen); +void nat64_local_csum(struct mbuf *m); void nat64_set_output_method(int); int nat64_get_output_method(void); Index: sys/netpfil/ipfw/nat64/nat64_translate.c =================================================================== --- sys/netpfil/ipfw/nat64/nat64_translate.c +++ sys/netpfil/ipfw/nat64/nat64_translate.c @@ -1228,7 +1228,7 @@ int nat64_do_handle_ip4(struct mbuf *m, struct in6_addr *saddr, struct in6_addr *daddr, uint16_t lport, struct nat64_config *cfg, - void *logdata) + uint8_t nat64_local, void *logdata) { struct nhop_object *nh; struct ip6_hdr ip6; @@ -1298,6 +1298,8 @@ switch (proto) { case IPPROTO_TCP: csum = &TCP(mtodo(m, hlen))->th_sum; + if (nat64_local != 0) + nat64_local_csum(m); if (lport != 0) { struct tcphdr *tcp = TCP(mtodo(m, hlen)); *csum = cksum_adjust(*csum, tcp->th_dport, lport); @@ -1307,6 +1309,8 @@ break; case IPPROTO_UDP: csum = &UDP(mtodo(m, hlen))->uh_sum; + if (nat64_local != 0) + nat64_local_csum(m); if (lport != 0) { struct udphdr *udp = UDP(mtodo(m, hlen)); *csum = cksum_adjust(*csum, udp->uh_dport, lport); @@ -1333,6 +1337,17 @@ return (NAT64RETURN); } +void +nat64_local_csum(struct mbuf *m) +{ + /* Hardware checksum offload is not supported for now */ + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + if ((m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) == 0) { + in_delayed_cksum(m); + m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; + } +} + int nat64_handle_icmp6(struct mbuf *m, int hlen, uint32_t aaddr, uint16_t aport, struct nat64_config *cfg, void *logdata) Index: sys/netpfil/ipfw/nat64/nat64clat.h =================================================================== --- sys/netpfil/ipfw/nat64/nat64clat.h +++ sys/netpfil/ipfw/nat64/nat64clat.h @@ -42,6 +42,7 @@ #define NAT64CLAT_FLAGSMASK \ (NAT64_LOG | NAT64_ALLOW_PRIVATE) /* flags to pass to userland */ char name[64]; + uint8_t clat_local; }; VNET_DECLARE(uint16_t, nat64clat_eid); Index: sys/netpfil/ipfw/nat64/nat64clat.c =================================================================== --- sys/netpfil/ipfw/nat64/nat64clat.c +++ sys/netpfil/ipfw/nat64/nat64clat.c @@ -108,7 +108,7 @@ } else logdata = NULL; return (nat64_do_handle_ip4(m, &saddr, &daddr, 0, &cfg->base, - logdata)); + cfg->clat_local, logdata)); } static int Index: sys/netpfil/ipfw/nat64/nat64clat_control.c =================================================================== --- sys/netpfil/ipfw/nat64/nat64clat_control.c +++ sys/netpfil/ipfw/nat64/nat64clat_control.c @@ -102,6 +102,7 @@ uc->clat_plen = cfg->base.clat_plen; uc->flags = cfg->base.flags & NAT64CLAT_FLAGSMASK; uc->set = cfg->no.set; + uc->clat_local = cfg->clat_local; strlcpy(uc->name, cfg->no.name, sizeof(uc->name)); } @@ -177,6 +178,7 @@ cfg->base.plat_plen = uc->plat_plen; cfg->base.clat_prefix = uc->clat_prefix; cfg->base.clat_plen = uc->clat_plen; + cfg->clat_local = uc->clat_local; cfg->base.flags = (uc->flags & NAT64CLAT_FLAGSMASK) | NAT64_CLATPFX | NAT64_PLATPFX; if (IN6_IS_ADDR_WKPFX(&cfg->base.plat_prefix)) Index: sys/netpfil/ipfw/nat64/nat64lsn.c =================================================================== --- sys/netpfil/ipfw/nat64/nat64lsn.c +++ sys/netpfil/ipfw/nat64/nat64lsn.c @@ -634,7 +634,7 @@ */ nat64_embed_ip4(&src6, cfg->base.plat_plen, htonl(f_id->src_ip)); ret = nat64_do_handle_ip4(*mp, &src6, &state->host->addr, port, - &cfg->base, logdata); + &cfg->base, 0, logdata); if (ret == NAT64SKIP) return (cfg->nomatch_verdict); if (ret == NAT64RETURN) Index: sys/netpfil/ipfw/nat64/nat64stl.c =================================================================== --- sys/netpfil/ipfw/nat64/nat64stl.c +++ sys/netpfil/ipfw/nat64/nat64stl.c @@ -109,7 +109,7 @@ } else logdata = NULL; return (nat64_do_handle_ip4(m, &saddr, &daddr, 0, &cfg->base, - logdata)); + 0, logdata)); } static int