mirror of https://github.com/F-Stack/f-stack.git
256 lines
7.9 KiB
C
256 lines
7.9 KiB
C
/*-
|
|
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
|
*
|
|
* Copyright (c) 2015-2019 Yandex LLC
|
|
* Copyright (c) 2015 Alexander V. Chernikov <melifaro@FreeBSD.org>
|
|
* Copyright (c) 2015-2019 Andrey V. Elsukov <ae@FreeBSD.org>
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* $FreeBSD$
|
|
*/
|
|
|
|
#ifndef _IP_FW_NAT64LSN_H_
|
|
#define _IP_FW_NAT64LSN_H_
|
|
|
|
#include "ip_fw_nat64.h"
|
|
#include "nat64_translate.h"
|
|
|
|
#define NAT64_MIN_PORT 1024
|
|
struct nat64lsn_host;
|
|
struct nat64lsn_alias;
|
|
|
|
struct nat64lsn_state {
|
|
/* IPv6 host entry keeps hash table to speedup state lookup */
|
|
CK_SLIST_ENTRY(nat64lsn_state) entries;
|
|
struct nat64lsn_host *host;
|
|
|
|
struct in6_addr ip6_dst; /* Destination IPv6 address */
|
|
|
|
in_addr_t ip_src; /* Alias IPv4 address */
|
|
in_addr_t ip_dst; /* Destination IPv4 address */
|
|
uint16_t dport; /* Destination port */
|
|
uint16_t sport; /* Source port */
|
|
|
|
uint32_t hval;
|
|
uint32_t flags; /* Internal flags */
|
|
uint16_t aport;
|
|
uint16_t timestamp; /* last used */
|
|
uint8_t proto;
|
|
uint8_t _spare[7];
|
|
};
|
|
|
|
struct nat64lsn_states_chunk {
|
|
struct nat64lsn_state state[64];
|
|
};
|
|
|
|
#define ISSET64(mask, bit) ((mask) & ((uint64_t)1 << (bit)))
|
|
#define ISSET32(mask, bit) ((mask) & ((uint32_t)1 << (bit)))
|
|
struct nat64lsn_pg {
|
|
CK_SLIST_ENTRY(nat64lsn_pg) entries;
|
|
|
|
uint16_t base_port;
|
|
uint16_t timestamp;
|
|
uint8_t proto;
|
|
uint8_t chunks_count;
|
|
uint8_t spare[2];
|
|
|
|
union {
|
|
uint64_t freemask64;
|
|
uint32_t freemask32[2];
|
|
uint64_t *freemask64_chunk;
|
|
uint32_t *freemask32_chunk;
|
|
void *freemask_chunk;
|
|
};
|
|
union {
|
|
struct nat64lsn_states_chunk *states;
|
|
struct nat64lsn_states_chunk **states_chunk;
|
|
};
|
|
};
|
|
|
|
#define CHUNK_BY_FADDR(p, a) ((a) & ((p)->chunks_count - 1))
|
|
|
|
#ifdef __LP64__
|
|
#define FREEMASK_CHUNK(p, v) \
|
|
((p)->chunks_count == 1 ? &(p)->freemask64 : \
|
|
&(p)->freemask64_chunk[CHUNK_BY_FADDR(p, v)])
|
|
#define FREEMASK_BITCOUNT(pg, faddr) \
|
|
bitcount64(*FREEMASK_CHUNK((pg), (faddr)))
|
|
#else
|
|
#define FREEMASK_CHUNK(p, v) \
|
|
((p)->chunks_count == 1 ? &(p)->freemask32[0] : \
|
|
&(p)->freemask32_chunk[CHUNK_BY_FADDR(p, v) * 2])
|
|
#define FREEMASK_BITCOUNT(pg, faddr) \
|
|
bitcount64(*(uint64_t *)FREEMASK_CHUNK((pg), (faddr)))
|
|
#endif /* !__LP64__ */
|
|
|
|
struct nat64lsn_pgchunk {
|
|
struct nat64lsn_pg *pgptr[32];
|
|
};
|
|
|
|
struct nat64lsn_aliaslink {
|
|
CK_SLIST_ENTRY(nat64lsn_aliaslink) alias_entries;
|
|
CK_SLIST_ENTRY(nat64lsn_aliaslink) host_entries;
|
|
struct nat64lsn_alias *alias;
|
|
};
|
|
|
|
CK_SLIST_HEAD(nat64lsn_aliaslink_slist, nat64lsn_aliaslink);
|
|
CK_SLIST_HEAD(nat64lsn_states_slist, nat64lsn_state);
|
|
CK_SLIST_HEAD(nat64lsn_hosts_slist, nat64lsn_host);
|
|
CK_SLIST_HEAD(nat64lsn_pg_slist, nat64lsn_pg);
|
|
|
|
struct nat64lsn_alias {
|
|
struct nat64lsn_aliaslink_slist hosts;
|
|
struct nat64lsn_pg_slist portgroups;
|
|
|
|
struct mtx lock;
|
|
in_addr_t addr; /* host byte order */
|
|
uint32_t hosts_count;
|
|
uint32_t portgroups_count;
|
|
uint32_t tcp_chunkmask;
|
|
uint32_t udp_chunkmask;
|
|
uint32_t icmp_chunkmask;
|
|
|
|
uint32_t tcp_pgidx;
|
|
uint32_t udp_pgidx;
|
|
uint32_t icmp_pgidx;
|
|
uint16_t timestamp;
|
|
uint16_t spare;
|
|
|
|
uint32_t tcp_pgmask[32];
|
|
uint32_t udp_pgmask[32];
|
|
uint32_t icmp_pgmask[32];
|
|
struct nat64lsn_pgchunk *tcp[32];
|
|
struct nat64lsn_pgchunk *udp[32];
|
|
struct nat64lsn_pgchunk *icmp[32];
|
|
|
|
/* pointer to PG that can be used for faster state allocation */
|
|
struct nat64lsn_pg *tcp_pg;
|
|
struct nat64lsn_pg *udp_pg;
|
|
struct nat64lsn_pg *icmp_pg;
|
|
};
|
|
#define ALIAS_LOCK_INIT(p) \
|
|
mtx_init(&(p)->lock, "alias_lock", NULL, MTX_DEF)
|
|
#define ALIAS_LOCK_DESTROY(p) mtx_destroy(&(p)->lock)
|
|
#define ALIAS_LOCK(p) mtx_lock(&(p)->lock)
|
|
#define ALIAS_UNLOCK(p) mtx_unlock(&(p)->lock)
|
|
|
|
#define NAT64LSN_HSIZE 256
|
|
#define NAT64LSN_MAX_HSIZE 4096
|
|
#define NAT64LSN_HOSTS_HSIZE 1024
|
|
|
|
struct nat64lsn_host {
|
|
struct in6_addr addr;
|
|
struct nat64lsn_aliaslink_slist aliases;
|
|
struct nat64lsn_states_slist *states_hash;
|
|
CK_SLIST_ENTRY(nat64lsn_host) entries;
|
|
uint32_t states_count;
|
|
uint32_t hval;
|
|
uint32_t flags;
|
|
#define NAT64LSN_DEADHOST 1
|
|
#define NAT64LSN_GROWHASH 2
|
|
uint16_t states_hashsize;
|
|
uint16_t timestamp;
|
|
struct mtx lock;
|
|
};
|
|
|
|
#define HOST_LOCK_INIT(p) \
|
|
mtx_init(&(p)->lock, "host_lock", NULL, MTX_DEF|MTX_NEW)
|
|
#define HOST_LOCK_DESTROY(p) mtx_destroy(&(p)->lock)
|
|
#define HOST_LOCK(p) mtx_lock(&(p)->lock)
|
|
#define HOST_UNLOCK(p) mtx_unlock(&(p)->lock)
|
|
|
|
VNET_DECLARE(uint16_t, nat64lsn_eid);
|
|
#define V_nat64lsn_eid VNET(nat64lsn_eid)
|
|
#define IPFW_TLV_NAT64LSN_NAME IPFW_TLV_EACTION_NAME(V_nat64lsn_eid)
|
|
|
|
/* Timestamp macro */
|
|
#define _CT ((int)time_uptime % 65536)
|
|
#define SET_AGE(x) (x) = _CT
|
|
#define GET_AGE(x) ((_CT >= (x)) ? _CT - (x): (int)65536 + _CT - (x))
|
|
|
|
STAILQ_HEAD(nat64lsn_job_head, nat64lsn_job_item);
|
|
|
|
struct nat64lsn_cfg {
|
|
struct named_object no;
|
|
|
|
struct nat64lsn_hosts_slist *hosts_hash;
|
|
struct nat64lsn_alias *aliases; /* array of aliases */
|
|
|
|
struct mtx lock;
|
|
uint32_t hosts_hashsize;
|
|
uint32_t hash_seed;
|
|
|
|
uint32_t prefix4; /* IPv4 prefix */
|
|
uint32_t pmask4; /* IPv4 prefix mask */
|
|
uint8_t plen4;
|
|
uint8_t nomatch_verdict;/* Return value on no-match */
|
|
|
|
uint32_t hosts_count; /* Number of items in host hash */
|
|
uint32_t states_chunks; /* Number of states chunks per PG */
|
|
uint32_t jmaxlen; /* Max jobqueue length */
|
|
uint16_t host_delete_delay; /* Stale host delete delay */
|
|
uint16_t pgchunk_delete_delay;
|
|
uint16_t pg_delete_delay; /* Stale portgroup del delay */
|
|
uint16_t st_syn_ttl; /* TCP syn expire */
|
|
uint16_t st_close_ttl; /* TCP fin expire */
|
|
uint16_t st_estab_ttl; /* TCP established expire */
|
|
uint16_t st_udp_ttl; /* UDP expire */
|
|
uint16_t st_icmp_ttl; /* ICMP expire */
|
|
|
|
struct nat64_config base;
|
|
#define NAT64LSN_FLAGSMASK (NAT64_LOG | NAT64_ALLOW_PRIVATE)
|
|
#define NAT64LSN_ANYPREFIX 0x00000100
|
|
|
|
struct mtx periodic_lock;
|
|
struct callout periodic;
|
|
struct callout jcallout;
|
|
struct vnet *vp;
|
|
struct nat64lsn_job_head jhead;
|
|
int jlen;
|
|
char name[64]; /* Nat instance name */
|
|
};
|
|
|
|
/* CFG_LOCK protects cfg->hosts_hash from modification */
|
|
#define CFG_LOCK_INIT(p) \
|
|
mtx_init(&(p)->lock, "cfg_lock", NULL, MTX_DEF)
|
|
#define CFG_LOCK_DESTROY(p) mtx_destroy(&(p)->lock)
|
|
#define CFG_LOCK(p) mtx_lock(&(p)->lock)
|
|
#define CFG_UNLOCK(p) mtx_unlock(&(p)->lock)
|
|
|
|
#define CALLOUT_LOCK_INIT(p) \
|
|
mtx_init(&(p)->periodic_lock, "periodic_lock", NULL, MTX_DEF)
|
|
#define CALLOUT_LOCK_DESTROY(p) mtx_destroy(&(p)->periodic_lock)
|
|
#define CALLOUT_LOCK(p) mtx_lock(&(p)->periodic_lock)
|
|
#define CALLOUT_UNLOCK(p) mtx_unlock(&(p)->periodic_lock)
|
|
|
|
struct nat64lsn_cfg *nat64lsn_init_instance(struct ip_fw_chain *ch,
|
|
in_addr_t prefix, int plen);
|
|
void nat64lsn_destroy_instance(struct nat64lsn_cfg *cfg);
|
|
void nat64lsn_start_instance(struct nat64lsn_cfg *cfg);
|
|
void nat64lsn_init_internal(void);
|
|
void nat64lsn_uninit_internal(void);
|
|
int ipfw_nat64lsn(struct ip_fw_chain *ch, struct ip_fw_args *args,
|
|
ipfw_insn *cmd, int *done);
|
|
|
|
#endif /* _IP_FW_NAT64LSN_H_ */
|