1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2015-2020 Yandex LLC 5 * Copyright (c) 2015 Alexander V. Chernikov <melifaro@FreeBSD.org> 6 * Copyright (c) 2015-2020 Andrey V. Elsukov <ae@FreeBSD.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #ifndef _IP_FW_NAT64LSN_H_ 31 #define _IP_FW_NAT64LSN_H_ 32 33 #include "ip_fw_nat64.h" 34 #include "nat64_translate.h" 35 36 #define NAT64_MIN_PORT 1024 37 struct nat64lsn_host; 38 struct nat64lsn_alias; 39 40 struct nat64lsn_state { 41 /* IPv6 host entry keeps hash table to speedup state lookup */ 42 CK_SLIST_ENTRY(nat64lsn_state) entries; 43 struct nat64lsn_host *host; 44 45 struct in6_addr ip6_dst; /* Destination IPv6 address */ 46 47 in_addr_t ip_src; /* Alias IPv4 address */ 48 in_addr_t ip_dst; /* Destination IPv4 address */ 49 uint16_t dport; /* Destination port */ 50 uint16_t sport; /* Source port */ 51 52 uint32_t hval; 53 uint32_t flags; /* Internal flags */ 54 uint16_t aport; 55 uint16_t timestamp; /* last used */ 56 uint8_t proto; 57 uint8_t _spare[7]; 58 }; 59 60 struct nat64lsn_states_chunk { 61 struct nat64lsn_state state[64]; 62 }; 63 64 #define ISSET64(mask, bit) ((mask) & ((uint64_t)1 << (bit))) 65 #define ISSET32(mask, bit) ((mask) & ((uint32_t)1 << (bit))) 66 struct nat64lsn_pg { 67 uint16_t base_port; 68 uint16_t timestamp; 69 uint8_t proto; 70 uint8_t chunks_count; 71 uint16_t flags; 72 #define NAT64LSN_DEADPG 1 73 74 union { 75 uint64_t freemask64; 76 uint32_t freemask32[2]; 77 uint64_t *freemask64_chunk; 78 uint32_t *freemask32_chunk; 79 void *freemask_chunk; 80 }; 81 union { 82 struct nat64lsn_states_chunk *states; 83 struct nat64lsn_states_chunk **states_chunk; 84 }; 85 /* 86 * An alias object holds chain of all allocated PGs. 87 * The chain is used mostly by expiration code. 88 */ 89 CK_SLIST_ENTRY(nat64lsn_pg) entries; 90 }; 91 92 #define CHUNK_BY_FADDR(p, a) ((a) & ((p)->chunks_count - 1)) 93 94 #ifdef __LP64__ 95 #define FREEMASK_CHUNK(p, v) \ 96 ((p)->chunks_count == 1 ? &(p)->freemask64 : \ 97 &(p)->freemask64_chunk[CHUNK_BY_FADDR(p, v)]) 98 #define FREEMASK_BITCOUNT(pg, faddr) \ 99 bitcount64(*FREEMASK_CHUNK((pg), (faddr))) 100 #else 101 #define FREEMASK_CHUNK(p, v) \ 102 ((p)->chunks_count == 1 ? &(p)->freemask32[0] : \ 103 &(p)->freemask32_chunk[CHUNK_BY_FADDR(p, v) * 2]) 104 #define FREEMASK_BITCOUNT(pg, faddr) \ 105 bitcount64(*(uint64_t *)FREEMASK_CHUNK((pg), (faddr))) 106 #endif /* !__LP64__ */ 107 108 struct nat64lsn_pgchunk { 109 struct nat64lsn_pg *pgptr[32]; 110 }; 111 112 struct nat64lsn_aliaslink { 113 CK_SLIST_ENTRY(nat64lsn_aliaslink) alias_entries; 114 CK_SLIST_ENTRY(nat64lsn_aliaslink) host_entries; 115 struct nat64lsn_alias *alias; 116 }; 117 118 CK_SLIST_HEAD(nat64lsn_aliaslink_slist, nat64lsn_aliaslink); 119 CK_SLIST_HEAD(nat64lsn_states_slist, nat64lsn_state); 120 CK_SLIST_HEAD(nat64lsn_hosts_slist, nat64lsn_host); 121 CK_SLIST_HEAD(nat64lsn_pg_slist, nat64lsn_pg); 122 123 struct nat64lsn_alias { 124 struct nat64lsn_aliaslink_slist hosts; 125 struct nat64lsn_pg_slist portgroups; 126 127 struct mtx lock; 128 in_addr_t addr; /* host byte order */ 129 uint32_t hosts_count; 130 131 uint16_t timestamp; 132 uint16_t tcp_pgcount; 133 uint16_t udp_pgcount; 134 uint16_t icmp_pgcount; 135 /* 136 * We keep PGs in chunks by 32 PGs in each. 137 * Each chunk allocated by demand, and then corresponding bit 138 * is set in chunkmask. 139 * 140 * Also we keep last used PG's index for each protocol. 141 * pgidx / 32 = index of pgchunk; 142 * pgidx % 32 = index of pgptr in pgchunk. 143 */ 144 uint32_t tcp_chunkmask; 145 uint32_t tcp_pgidx; 146 147 uint32_t udp_chunkmask; 148 uint32_t udp_pgidx; 149 150 uint32_t icmp_chunkmask; 151 uint32_t icmp_pgidx; 152 /* 153 * Each pgchunk keeps 32 pointers to PGs. If pgptr pointer is 154 * valid, we have corresponding bit set in the pgmask. 155 */ 156 uint32_t tcp_pgmask[32]; 157 uint32_t udp_pgmask[32]; 158 uint32_t icmp_pgmask[32]; 159 160 struct nat64lsn_pgchunk *tcp[32]; 161 struct nat64lsn_pgchunk *udp[32]; 162 struct nat64lsn_pgchunk *icmp[32]; 163 }; 164 #define ALIAS_LOCK_INIT(p) \ 165 mtx_init(&(p)->lock, "alias_lock", NULL, MTX_DEF) 166 #define ALIAS_LOCK_DESTROY(p) mtx_destroy(&(p)->lock) 167 #define ALIAS_LOCK(p) mtx_lock(&(p)->lock) 168 #define ALIAS_UNLOCK(p) mtx_unlock(&(p)->lock) 169 170 #define NAT64LSN_HSIZE 256 171 #define NAT64LSN_MAX_HSIZE 4096 172 #define NAT64LSN_HOSTS_HSIZE 1024 173 174 struct nat64lsn_host { 175 struct in6_addr addr; 176 struct nat64lsn_aliaslink_slist aliases; 177 struct nat64lsn_states_slist *states_hash; 178 CK_SLIST_ENTRY(nat64lsn_host) entries; 179 uint32_t states_count; 180 uint32_t hval; 181 uint32_t flags; 182 #define NAT64LSN_DEADHOST 1 183 #define NAT64LSN_GROWHASH 2 184 uint16_t states_hashsize; 185 uint16_t timestamp; 186 struct mtx lock; 187 }; 188 189 #define HOST_LOCK_INIT(p) \ 190 mtx_init(&(p)->lock, "host_lock", NULL, MTX_DEF|MTX_NEW) 191 #define HOST_LOCK_DESTROY(p) mtx_destroy(&(p)->lock) 192 #define HOST_LOCK(p) mtx_lock(&(p)->lock) 193 #define HOST_UNLOCK(p) mtx_unlock(&(p)->lock) 194 195 VNET_DECLARE(uint32_t, nat64lsn_eid); 196 #define V_nat64lsn_eid VNET(nat64lsn_eid) 197 #define IPFW_TLV_NAT64LSN_NAME IPFW_TLV_EACTION_NAME(V_nat64lsn_eid) 198 199 /* Timestamp macro */ 200 #define _CT ((int)time_uptime % 65536) 201 #define SET_AGE(x) (x) = _CT 202 #define GET_AGE(x) ((_CT >= (x)) ? _CT - (x): (int)65536 + _CT - (x)) 203 204 STAILQ_HEAD(nat64lsn_job_head, nat64lsn_job_item); 205 206 struct nat64lsn_cfg { 207 struct nat64lsn_hosts_slist *hosts_hash; 208 struct nat64lsn_alias *aliases; /* array of aliases */ 209 210 struct mtx lock; 211 uint32_t hosts_hashsize; 212 uint32_t hash_seed; 213 214 uint32_t prefix4; /* IPv4 prefix */ 215 uint32_t pmask4; /* IPv4 prefix mask */ 216 uint8_t plen4; 217 uint8_t nomatch_verdict;/* Return value on no-match */ 218 219 uint32_t hosts_count; /* Number of items in host hash */ 220 uint32_t states_chunks; /* Number of states chunks per PG */ 221 uint32_t jmaxlen; /* Max jobqueue length */ 222 uint16_t host_delete_delay; /* Stale host delete delay */ 223 uint16_t pgchunk_delete_delay; 224 uint16_t pg_delete_delay; /* Stale portgroup del delay */ 225 uint16_t st_syn_ttl; /* TCP syn expire */ 226 uint16_t st_close_ttl; /* TCP fin expire */ 227 uint16_t st_estab_ttl; /* TCP established expire */ 228 uint16_t st_udp_ttl; /* UDP expire */ 229 uint16_t st_icmp_ttl; /* ICMP expire */ 230 231 struct nat64_config base; 232 #define NAT64LSN_FLAGSMASK (NAT64_LOG | NAT64_ALLOW_PRIVATE | \ 233 NAT64LSN_ALLOW_SWAPCONF) 234 #define NAT64LSN_ANYPREFIX 0x00000100 235 236 struct mtx periodic_lock; 237 struct callout periodic; 238 struct callout jcallout; 239 struct vnet *vp; 240 struct nat64lsn_job_head jhead; 241 int jlen; 242 char name[64]; /* Nat instance name */ 243 }; 244 245 struct nat64lsn_instance { 246 struct named_object no; 247 struct nat64lsn_cfg *cfg; 248 char name[64]; /* Nat instance name */ 249 }; 250 251 /* CFG_LOCK protects cfg->hosts_hash from modification */ 252 #define CFG_LOCK_INIT(p) \ 253 mtx_init(&(p)->lock, "cfg_lock", NULL, MTX_DEF) 254 #define CFG_LOCK_DESTROY(p) mtx_destroy(&(p)->lock) 255 #define CFG_LOCK(p) mtx_lock(&(p)->lock) 256 #define CFG_UNLOCK(p) mtx_unlock(&(p)->lock) 257 258 #define CALLOUT_LOCK_INIT(p) \ 259 mtx_init(&(p)->periodic_lock, "periodic_lock", NULL, MTX_DEF) 260 #define CALLOUT_LOCK_DESTROY(p) mtx_destroy(&(p)->periodic_lock) 261 #define CALLOUT_LOCK(p) mtx_lock(&(p)->periodic_lock) 262 #define CALLOUT_UNLOCK(p) mtx_unlock(&(p)->periodic_lock) 263 264 MALLOC_DECLARE(M_NAT64LSN); 265 266 struct nat64lsn_cfg *nat64lsn_init_config(struct ip_fw_chain *ch, 267 in_addr_t prefix, int plen); 268 void nat64lsn_destroy_config(struct nat64lsn_cfg *cfg); 269 void nat64lsn_start_instance(struct nat64lsn_cfg *cfg); 270 void nat64lsn_init_internal(void); 271 void nat64lsn_uninit_internal(void); 272 int ipfw_nat64lsn(struct ip_fw_chain *ch, struct ip_fw_args *args, 273 ipfw_insn *cmd, int *done); 274 275 #endif /* _IP_FW_NAT64LSN_H_ */ 276