Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */ 2 : : /* 3 : : * Connection state tracking for netfilter. This is separated from, 4 : : * but required by, the (future) NAT layer; it can also be used by an iptables 5 : : * extension. 6 : : * 7 : : * 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> 8 : : * - generalize L3 protocol dependent part. 9 : : * 10 : : * Derived from include/linux/netfiter_ipv4/ip_conntrack.h 11 : : */ 12 : : 13 : : #ifndef _NF_CONNTRACK_H 14 : : #define _NF_CONNTRACK_H 15 : : 16 : : #include <linux/bitops.h> 17 : : #include <linux/compiler.h> 18 : : 19 : : #include <linux/netfilter/nf_conntrack_common.h> 20 : : #include <linux/netfilter/nf_conntrack_tcp.h> 21 : : #include <linux/netfilter/nf_conntrack_dccp.h> 22 : : #include <linux/netfilter/nf_conntrack_sctp.h> 23 : : #include <linux/netfilter/nf_conntrack_proto_gre.h> 24 : : 25 : : #include <net/netfilter/nf_conntrack_tuple.h> 26 : : 27 : : struct nf_ct_udp { 28 : : unsigned long stream_ts; 29 : : }; 30 : : 31 : : /* per conntrack: protocol private data */ 32 : : union nf_conntrack_proto { 33 : : /* insert conntrack proto private data here */ 34 : : struct nf_ct_dccp dccp; 35 : : struct ip_ct_sctp sctp; 36 : : struct ip_ct_tcp tcp; 37 : : struct nf_ct_udp udp; 38 : : struct nf_ct_gre gre; 39 : : unsigned int tmpl_padto; 40 : : }; 41 : : 42 : : union nf_conntrack_expect_proto { 43 : : /* insert expect proto private data here */ 44 : : }; 45 : : 46 : : struct nf_conntrack_net { 47 : : unsigned int users4; 48 : : unsigned int users6; 49 : : unsigned int users_bridge; 50 : : }; 51 : : 52 : : #include <linux/types.h> 53 : : #include <linux/skbuff.h> 54 : : 55 : : #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 56 : : #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 57 : : 58 : : struct nf_conn { 59 : : /* Usage count in here is 1 for hash table, 1 per skb, 60 : : * plus 1 for any connection(s) we are `master' for 61 : : * 62 : : * Hint, SKB address this struct and refcnt via skb->_nfct and 63 : : * helpers nf_conntrack_get() and nf_conntrack_put(). 64 : : * Helper nf_ct_put() equals nf_conntrack_put() by dec refcnt, 65 : : * beware nf_ct_get() is different and don't inc refcnt. 66 : : */ 67 : : struct nf_conntrack ct_general; 68 : : 69 : : spinlock_t lock; 70 : : /* jiffies32 when this ct is considered dead */ 71 : : u32 timeout; 72 : : 73 : : #ifdef CONFIG_NF_CONNTRACK_ZONES 74 : : struct nf_conntrack_zone zone; 75 : : #endif 76 : : /* XXX should I move this to the tail ? - Y.K */ 77 : : /* These are my tuples; original and reply */ 78 : : struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; 79 : : 80 : : /* Have we seen traffic both ways yet? (bitset) */ 81 : : unsigned long status; 82 : : 83 : : u16 cpu; 84 : : possible_net_t ct_net; 85 : : 86 : : #if IS_ENABLED(CONFIG_NF_NAT) 87 : : struct hlist_node nat_bysource; 88 : : #endif 89 : : /* all members below initialized via memset */ 90 : : struct { } __nfct_init_offset; 91 : : 92 : : /* If we were expected by an expectation, this will be it */ 93 : : struct nf_conn *master; 94 : : 95 : : #if defined(CONFIG_NF_CONNTRACK_MARK) 96 : : u_int32_t mark; 97 : : #endif 98 : : 99 : : #ifdef CONFIG_NF_CONNTRACK_SECMARK 100 : : u_int32_t secmark; 101 : : #endif 102 : : 103 : : /* Extensions */ 104 : : struct nf_ct_ext *ext; 105 : : 106 : : /* Storage reserved for other modules, must be the last member */ 107 : : union nf_conntrack_proto proto; 108 : : }; 109 : : 110 : : static inline struct nf_conn * 111 : : nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash) 112 : : { 113 : : return container_of(hash, struct nf_conn, 114 : : tuplehash[hash->tuple.dst.dir]); 115 : : } 116 : : 117 : : static inline u_int16_t nf_ct_l3num(const struct nf_conn *ct) 118 : : { 119 : : return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; 120 : : } 121 : : 122 : : static inline u_int8_t nf_ct_protonum(const struct nf_conn *ct) 123 : : { 124 : : return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; 125 : : } 126 : : 127 : : #define nf_ct_tuple(ct, dir) (&(ct)->tuplehash[dir].tuple) 128 : : 129 : : /* get master conntrack via master expectation */ 130 : : #define master_ct(conntr) (conntr->master) 131 : : 132 : : extern struct net init_net; 133 : : 134 : : static inline struct net *nf_ct_net(const struct nf_conn *ct) 135 : : { 136 : : return read_pnet(&ct->ct_net); 137 : : } 138 : : 139 : : /* Alter reply tuple (maybe alter helper). */ 140 : : void nf_conntrack_alter_reply(struct nf_conn *ct, 141 : : const struct nf_conntrack_tuple *newreply); 142 : : 143 : : /* Is this tuple taken? (ignoring any belonging to the given 144 : : conntrack). */ 145 : : int nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple, 146 : : const struct nf_conn *ignored_conntrack); 147 : : 148 : : /* Return conntrack_info and tuple hash for given skb. */ 149 : : static inline struct nf_conn * 150 : : nf_ct_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo) 151 : : { 152 : : unsigned long nfct = skb_get_nfct(skb); 153 : : 154 : 0 : *ctinfo = nfct & NFCT_INFOMASK; 155 : 0 : return (struct nf_conn *)(nfct & NFCT_PTRMASK); 156 : : } 157 : : 158 : : /* decrement reference count on a conntrack */ 159 : : static inline void nf_ct_put(struct nf_conn *ct) 160 : : { 161 : : WARN_ON(!ct); 162 : : nf_conntrack_put(&ct->ct_general); 163 : : } 164 : : 165 : : /* Protocol module loading */ 166 : : int nf_ct_l3proto_try_module_get(unsigned short l3proto); 167 : : void nf_ct_l3proto_module_put(unsigned short l3proto); 168 : : 169 : : /* load module; enable/disable conntrack in this namespace */ 170 : : int nf_ct_netns_get(struct net *net, u8 nfproto); 171 : : void nf_ct_netns_put(struct net *net, u8 nfproto); 172 : : 173 : : /* 174 : : * Allocate a hashtable of hlist_head (if nulls == 0), 175 : : * or hlist_nulls_head (if nulls == 1) 176 : : */ 177 : : void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls); 178 : : 179 : : int nf_conntrack_hash_check_insert(struct nf_conn *ct); 180 : : bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report); 181 : : 182 : : bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, 183 : : u_int16_t l3num, struct net *net, 184 : : struct nf_conntrack_tuple *tuple); 185 : : 186 : : void __nf_ct_refresh_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo, 187 : : const struct sk_buff *skb, 188 : : u32 extra_jiffies, bool do_acct); 189 : : 190 : : /* Refresh conntrack for this many jiffies and do accounting */ 191 : : static inline void nf_ct_refresh_acct(struct nf_conn *ct, 192 : : enum ip_conntrack_info ctinfo, 193 : : const struct sk_buff *skb, 194 : : u32 extra_jiffies) 195 : : { 196 : : __nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, true); 197 : : } 198 : : 199 : : /* Refresh conntrack for this many jiffies */ 200 : : static inline void nf_ct_refresh(struct nf_conn *ct, 201 : : const struct sk_buff *skb, 202 : : u32 extra_jiffies) 203 : : { 204 : : __nf_ct_refresh_acct(ct, 0, skb, extra_jiffies, false); 205 : : } 206 : : 207 : : /* kill conntrack and do accounting */ 208 : : bool nf_ct_kill_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo, 209 : : const struct sk_buff *skb); 210 : : 211 : : /* kill conntrack without accounting */ 212 : : static inline bool nf_ct_kill(struct nf_conn *ct) 213 : : { 214 : : return nf_ct_delete(ct, 0, 0); 215 : : } 216 : : 217 : : /* Set all unconfirmed conntrack as dying */ 218 : : void nf_ct_unconfirmed_destroy(struct net *); 219 : : 220 : : /* Iterate over all conntracks: if iter returns true, it's deleted. */ 221 : : void nf_ct_iterate_cleanup_net(struct net *net, 222 : : int (*iter)(struct nf_conn *i, void *data), 223 : : void *data, u32 portid, int report); 224 : : 225 : : /* also set unconfirmed conntracks as dying. Only use in module exit path. */ 226 : : void nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data), 227 : : void *data); 228 : : 229 : : struct nf_conntrack_zone; 230 : : 231 : : void nf_conntrack_free(struct nf_conn *ct); 232 : : struct nf_conn *nf_conntrack_alloc(struct net *net, 233 : : const struct nf_conntrack_zone *zone, 234 : : const struct nf_conntrack_tuple *orig, 235 : : const struct nf_conntrack_tuple *repl, 236 : : gfp_t gfp); 237 : : 238 : : static inline int nf_ct_is_template(const struct nf_conn *ct) 239 : : { 240 : : return test_bit(IPS_TEMPLATE_BIT, &ct->status); 241 : : } 242 : : 243 : : /* It's confirmed if it is, or has been in the hash table. */ 244 : : static inline int nf_ct_is_confirmed(const struct nf_conn *ct) 245 : : { 246 : : return test_bit(IPS_CONFIRMED_BIT, &ct->status); 247 : : } 248 : : 249 : : static inline int nf_ct_is_dying(const struct nf_conn *ct) 250 : : { 251 : : return test_bit(IPS_DYING_BIT, &ct->status); 252 : : } 253 : : 254 : : /* Packet is received from loopback */ 255 : : static inline bool nf_is_loopback_packet(const struct sk_buff *skb) 256 : : { 257 : : return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK; 258 : : } 259 : : 260 : : #define nfct_time_stamp ((u32)(jiffies)) 261 : : 262 : : /* jiffies until ct expires, 0 if already expired */ 263 : : static inline unsigned long nf_ct_expires(const struct nf_conn *ct) 264 : : { 265 : : s32 timeout = ct->timeout - nfct_time_stamp; 266 : : 267 : : return timeout > 0 ? timeout : 0; 268 : : } 269 : : 270 : : static inline bool nf_ct_is_expired(const struct nf_conn *ct) 271 : : { 272 : : return (__s32)(ct->timeout - nfct_time_stamp) <= 0; 273 : : } 274 : : 275 : : /* use after obtaining a reference count */ 276 : : static inline bool nf_ct_should_gc(const struct nf_conn *ct) 277 : : { 278 : : return nf_ct_is_expired(ct) && nf_ct_is_confirmed(ct) && 279 : : !nf_ct_is_dying(ct); 280 : : } 281 : : 282 : : struct kernel_param; 283 : : 284 : : int nf_conntrack_set_hashsize(const char *val, const struct kernel_param *kp); 285 : : int nf_conntrack_hash_resize(unsigned int hashsize); 286 : : 287 : : extern struct hlist_nulls_head *nf_conntrack_hash; 288 : : extern unsigned int nf_conntrack_htable_size; 289 : : extern seqcount_t nf_conntrack_generation; 290 : : extern unsigned int nf_conntrack_max; 291 : : 292 : : /* must be called with rcu read lock held */ 293 : : static inline void 294 : : nf_conntrack_get_ht(struct hlist_nulls_head **hash, unsigned int *hsize) 295 : : { 296 : : struct hlist_nulls_head *hptr; 297 : : unsigned int sequence, hsz; 298 : : 299 : : do { 300 : : sequence = read_seqcount_begin(&nf_conntrack_generation); 301 : : hsz = nf_conntrack_htable_size; 302 : : hptr = nf_conntrack_hash; 303 : : } while (read_seqcount_retry(&nf_conntrack_generation, sequence)); 304 : : 305 : : *hash = hptr; 306 : : *hsize = hsz; 307 : : } 308 : : 309 : : struct nf_conn *nf_ct_tmpl_alloc(struct net *net, 310 : : const struct nf_conntrack_zone *zone, 311 : : gfp_t flags); 312 : : void nf_ct_tmpl_free(struct nf_conn *tmpl); 313 : : 314 : : u32 nf_ct_get_id(const struct nf_conn *ct); 315 : : 316 : : static inline void 317 : : nf_ct_set(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info info) 318 : : { 319 : : skb_set_nfct(skb, (unsigned long)ct | info); 320 : : } 321 : : 322 : : #define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) 323 : : #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) 324 : : #define NF_CT_STAT_ADD_ATOMIC(net, count, v) this_cpu_add((net)->ct.stat->count, (v)) 325 : : 326 : : #define MODULE_ALIAS_NFCT_HELPER(helper) \ 327 : : MODULE_ALIAS("nfct-helper-" helper) 328 : : 329 : : #endif /* _NF_CONNTRACK_H */