Home | History | Annotate | Download | only in netfilter_ipv4
      1 #ifndef _IP_CONNTRACK_H
      2 #define _IP_CONNTRACK_H
      3 
      4 #include <linux/netfilter/nf_conntrack_common.h>
      5 
      6 #ifdef __KERNEL__
      7 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
      8 #include <linux/bitops.h>
      9 #include <linux/compiler.h>
     10 #include <asm/atomic.h>
     11 
     12 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
     13 #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
     14 #include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
     15 #include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
     16 
     17 /* per conntrack: protocol private data */
     18 union ip_conntrack_proto {
     19 	/* insert conntrack proto private data here */
     20 	struct ip_ct_gre gre;
     21 	struct ip_ct_sctp sctp;
     22 	struct ip_ct_tcp tcp;
     23 	struct ip_ct_icmp icmp;
     24 };
     25 
     26 union ip_conntrack_expect_proto {
     27 	/* insert expect proto private data here */
     28 };
     29 
     30 /* Add protocol helper include file here */
     31 #include <linux/netfilter_ipv4/ip_conntrack_h323.h>
     32 #include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
     33 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
     34 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
     35 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
     36 
     37 /* per conntrack: application helper private data */
     38 union ip_conntrack_help {
     39 	/* insert conntrack helper private data (master) here */
     40 	struct ip_ct_h323_master ct_h323_info;
     41 	struct ip_ct_pptp_master ct_pptp_info;
     42 	struct ip_ct_ftp_master ct_ftp_info;
     43 	struct ip_ct_irc_master ct_irc_info;
     44 };
     45 
     46 #ifdef CONFIG_IP_NF_NAT_NEEDED
     47 #include <linux/netfilter_ipv4/ip_nat.h>
     48 #include <linux/netfilter_ipv4/ip_nat_pptp.h>
     49 
     50 /* per conntrack: nat application helper private data */
     51 union ip_conntrack_nat_help {
     52 	/* insert nat helper private data here */
     53 	struct ip_nat_pptp nat_pptp_info;
     54 };
     55 #endif
     56 
     57 #include <linux/types.h>
     58 #include <linux/skbuff.h>
     59 
     60 #ifdef CONFIG_NETFILTER_DEBUG
     61 #define IP_NF_ASSERT(x)							\
     62 do {									\
     63 	if (!(x))							\
     64 		/* Wooah!  I'm tripping my conntrack in a frenzy of	\
     65 		   netplay... */					\
     66 		printk("NF_IP_ASSERT: %s:%i(%s)\n",			\
     67 		       __FILE__, __LINE__, __FUNCTION__);		\
     68 } while(0)
     69 #else
     70 #define IP_NF_ASSERT(x)
     71 #endif
     72 
     73 struct ip_conntrack_helper;
     74 
     75 struct ip_conntrack
     76 {
     77 	/* Usage count in here is 1 for hash table/destruct timer, 1 per skb,
     78            plus 1 for any connection(s) we are `master' for */
     79 	struct nf_conntrack ct_general;
     80 
     81 	/* Have we seen traffic both ways yet? (bitset) */
     82 	unsigned long status;
     83 
     84 	/* Timer function; drops refcnt when it goes off. */
     85 	struct timer_list timeout;
     86 
     87 #ifdef CONFIG_IP_NF_CT_ACCT
     88 	/* Accounting Information (same cache line as other written members) */
     89 	struct ip_conntrack_counter counters[IP_CT_DIR_MAX];
     90 #endif
     91 	/* If we were expected by an expectation, this will be it */
     92 	struct ip_conntrack *master;
     93 
     94 	/* Current number of expected connections */
     95 	unsigned int expecting;
     96 
     97 	/* Unique ID that identifies this conntrack*/
     98 	unsigned int id;
     99 
    100 	/* Helper, if any. */
    101 	struct ip_conntrack_helper *helper;
    102 
    103 	/* Storage reserved for other modules: */
    104 	union ip_conntrack_proto proto;
    105 
    106 	union ip_conntrack_help help;
    107 
    108 #ifdef CONFIG_IP_NF_NAT_NEEDED
    109 	struct {
    110 		struct ip_nat_info info;
    111 		union ip_conntrack_nat_help help;
    112 #if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
    113 	defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
    114 		int masq_index;
    115 #endif
    116 	} nat;
    117 #endif /* CONFIG_IP_NF_NAT_NEEDED */
    118 
    119 #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
    120 	u_int32_t mark;
    121 #endif
    122 
    123 #ifdef CONFIG_IP_NF_CONNTRACK_SECMARK
    124 	u_int32_t secmark;
    125 #endif
    126 
    127 	/* Traversed often, so hopefully in different cacheline to top */
    128 	/* These are my tuples; original and reply */
    129 	struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
    130 };
    131 
    132 struct ip_conntrack_expect
    133 {
    134 	/* Internal linked list (global expectation list) */
    135 	struct list_head list;
    136 
    137 	/* We expect this tuple, with the following mask */
    138 	struct ip_conntrack_tuple tuple, mask;
    139 
    140 	/* Function to call after setup and insertion */
    141 	void (*expectfn)(struct ip_conntrack *new,
    142 			 struct ip_conntrack_expect *this);
    143 
    144 	/* The conntrack of the master connection */
    145 	struct ip_conntrack *master;
    146 
    147 	/* Timer function; deletes the expectation. */
    148 	struct timer_list timeout;
    149 
    150 	/* Usage count. */
    151 	atomic_t use;
    152 
    153 	/* Unique ID */
    154 	unsigned int id;
    155 
    156 	/* Flags */
    157 	unsigned int flags;
    158 
    159 #ifdef CONFIG_IP_NF_NAT_NEEDED
    160 	u_int32_t saved_ip;
    161 	/* This is the original per-proto part, used to map the
    162 	 * expected connection the way the recipient expects. */
    163 	union ip_conntrack_manip_proto saved_proto;
    164 	/* Direction relative to the master connection. */
    165 	enum ip_conntrack_dir dir;
    166 #endif
    167 };
    168 
    169 #define IP_CT_EXPECT_PERMANENT	0x1
    170 
    171 static inline struct ip_conntrack *
    172 tuplehash_to_ctrack(const struct ip_conntrack_tuple_hash *hash)
    173 {
    174 	return container_of(hash, struct ip_conntrack,
    175 			    tuplehash[hash->tuple.dst.dir]);
    176 }
    177 
    178 /* get master conntrack via master expectation */
    179 #define master_ct(conntr) (conntr->master)
    180 
    181 /* Alter reply tuple (maybe alter helper). */
    182 extern void
    183 ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
    184 			 const struct ip_conntrack_tuple *newreply);
    185 
    186 /* Is this tuple taken? (ignoring any belonging to the given
    187    conntrack). */
    188 extern int
    189 ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
    190 			 const struct ip_conntrack *ignored_conntrack);
    191 
    192 /* Return conntrack_info and tuple hash for given skb. */
    193 static inline struct ip_conntrack *
    194 ip_conntrack_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
    195 {
    196 	*ctinfo = skb->nfctinfo;
    197 	return (struct ip_conntrack *)skb->nfct;
    198 }
    199 
    200 /* decrement reference count on a conntrack */
    201 static inline void
    202 ip_conntrack_put(struct ip_conntrack *ct)
    203 {
    204 	IP_NF_ASSERT(ct);
    205 	nf_conntrack_put(&ct->ct_general);
    206 }
    207 
    208 extern int invert_tuplepr(struct ip_conntrack_tuple *inverse,
    209 			  const struct ip_conntrack_tuple *orig);
    210 
    211 extern void __ip_ct_refresh_acct(struct ip_conntrack *ct,
    212 			         enum ip_conntrack_info ctinfo,
    213 			         const struct sk_buff *skb,
    214 			         unsigned long extra_jiffies,
    215 				 int do_acct);
    216 
    217 /* Refresh conntrack for this many jiffies and do accounting */
    218 static inline void ip_ct_refresh_acct(struct ip_conntrack *ct,
    219 				      enum ip_conntrack_info ctinfo,
    220 				      const struct sk_buff *skb,
    221 				      unsigned long extra_jiffies)
    222 {
    223 	__ip_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1);
    224 }
    225 
    226 /* Refresh conntrack for this many jiffies */
    227 static inline void ip_ct_refresh(struct ip_conntrack *ct,
    228 				 const struct sk_buff *skb,
    229 				 unsigned long extra_jiffies)
    230 {
    231 	__ip_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0);
    232 }
    233 
    234 /* These are for NAT.  Icky. */
    235 /* Update TCP window tracking data when NAT mangles the packet */
    236 extern void ip_conntrack_tcp_update(struct sk_buff *skb,
    237 				    struct ip_conntrack *conntrack,
    238 				    enum ip_conntrack_dir dir);
    239 
    240 /* Call me when a conntrack is destroyed. */
    241 extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
    242 
    243 /* Fake conntrack entry for untracked connections */
    244 extern struct ip_conntrack ip_conntrack_untracked;
    245 
    246 /* Returns new sk_buff, or NULL */
    247 struct sk_buff *
    248 ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user);
    249 
    250 /* Iterate over all conntracks: if iter returns true, it's deleted. */
    251 extern void
    252 ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *data),
    253 		      void *data);
    254 
    255 extern struct ip_conntrack_helper *
    256 __ip_conntrack_helper_find_byname(const char *);
    257 extern struct ip_conntrack_helper *
    258 ip_conntrack_helper_find_get(const struct ip_conntrack_tuple *tuple);
    259 extern void ip_conntrack_helper_put(struct ip_conntrack_helper *helper);
    260 
    261 extern struct ip_conntrack_protocol *
    262 __ip_conntrack_proto_find(u_int8_t protocol);
    263 extern struct ip_conntrack_protocol *
    264 ip_conntrack_proto_find_get(u_int8_t protocol);
    265 extern void ip_conntrack_proto_put(struct ip_conntrack_protocol *proto);
    266 
    267 extern void ip_ct_remove_expectations(struct ip_conntrack *ct);
    268 
    269 extern struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *,
    270 					       struct ip_conntrack_tuple *);
    271 
    272 extern void ip_conntrack_free(struct ip_conntrack *ct);
    273 
    274 extern void ip_conntrack_hash_insert(struct ip_conntrack *ct);
    275 
    276 extern struct ip_conntrack_expect *
    277 __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
    278 
    279 extern struct ip_conntrack_expect *
    280 ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple);
    281 
    282 extern struct ip_conntrack_tuple_hash *
    283 __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
    284                     const struct ip_conntrack *ignored_conntrack);
    285 
    286 extern void ip_conntrack_flush(void);
    287 
    288 /* It's confirmed if it is, or has been in the hash table. */
    289 static inline int is_confirmed(struct ip_conntrack *ct)
    290 {
    291 	return test_bit(IPS_CONFIRMED_BIT, &ct->status);
    292 }
    293 
    294 static inline int is_dying(struct ip_conntrack *ct)
    295 {
    296 	return test_bit(IPS_DYING_BIT, &ct->status);
    297 }
    298 
    299 extern unsigned int ip_conntrack_htable_size;
    300 extern int ip_conntrack_checksum;
    301 
    302 #define CONNTRACK_STAT_INC(count) (__get_cpu_var(ip_conntrack_stat).count++)
    303 
    304 #ifdef CONFIG_IP_NF_CONNTRACK_EVENTS
    305 #include <linux/notifier.h>
    306 #include <linux/interrupt.h>
    307 
    308 struct ip_conntrack_ecache {
    309 	struct ip_conntrack *ct;
    310 	unsigned int events;
    311 };
    312 DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache);
    313 
    314 #define CONNTRACK_ECACHE(x)	(__get_cpu_var(ip_conntrack_ecache).x)
    315 
    316 extern struct atomic_notifier_head ip_conntrack_chain;
    317 extern struct atomic_notifier_head ip_conntrack_expect_chain;
    318 
    319 static inline int ip_conntrack_register_notifier(struct notifier_block *nb)
    320 {
    321 	return atomic_notifier_chain_register(&ip_conntrack_chain, nb);
    322 }
    323 
    324 static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb)
    325 {
    326 	return atomic_notifier_chain_unregister(&ip_conntrack_chain, nb);
    327 }
    328 
    329 static inline int
    330 ip_conntrack_expect_register_notifier(struct notifier_block *nb)
    331 {
    332 	return atomic_notifier_chain_register(&ip_conntrack_expect_chain, nb);
    333 }
    334 
    335 static inline int
    336 ip_conntrack_expect_unregister_notifier(struct notifier_block *nb)
    337 {
    338 	return atomic_notifier_chain_unregister(&ip_conntrack_expect_chain,
    339 			nb);
    340 }
    341 
    342 extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct);
    343 extern void __ip_ct_event_cache_init(struct ip_conntrack *ct);
    344 
    345 static inline void
    346 ip_conntrack_event_cache(enum ip_conntrack_events event,
    347 			 const struct sk_buff *skb)
    348 {
    349 	struct ip_conntrack *ct = (struct ip_conntrack *)skb->nfct;
    350 	struct ip_conntrack_ecache *ecache;
    351 
    352 	local_bh_disable();
    353 	ecache = &__get_cpu_var(ip_conntrack_ecache);
    354 	if (ct != ecache->ct)
    355 		__ip_ct_event_cache_init(ct);
    356 	ecache->events |= event;
    357 	local_bh_enable();
    358 }
    359 
    360 static inline void ip_conntrack_event(enum ip_conntrack_events event,
    361 				      struct ip_conntrack *ct)
    362 {
    363 	if (is_confirmed(ct) && !is_dying(ct))
    364 		atomic_notifier_call_chain(&ip_conntrack_chain, event, ct);
    365 }
    366 
    367 static inline void
    368 ip_conntrack_expect_event(enum ip_conntrack_expect_events event,
    369 			  struct ip_conntrack_expect *exp)
    370 {
    371 	atomic_notifier_call_chain(&ip_conntrack_expect_chain, event, exp);
    372 }
    373 #else /* CONFIG_IP_NF_CONNTRACK_EVENTS */
    374 static inline void ip_conntrack_event_cache(enum ip_conntrack_events event,
    375 					    const struct sk_buff *skb) {}
    376 static inline void ip_conntrack_event(enum ip_conntrack_events event,
    377 				      struct ip_conntrack *ct) {}
    378 static inline void ip_ct_deliver_cached_events(const struct ip_conntrack *ct) {}
    379 static inline void
    380 ip_conntrack_expect_event(enum ip_conntrack_expect_events event,
    381 			  struct ip_conntrack_expect *exp) {}
    382 #endif /* CONFIG_IP_NF_CONNTRACK_EVENTS */
    383 
    384 #ifdef CONFIG_IP_NF_NAT_NEEDED
    385 static inline int ip_nat_initialized(struct ip_conntrack *conntrack,
    386 				     enum ip_nat_manip_type manip)
    387 {
    388 	if (manip == IP_NAT_MANIP_SRC)
    389 		return test_bit(IPS_SRC_NAT_DONE_BIT, &conntrack->status);
    390 	return test_bit(IPS_DST_NAT_DONE_BIT, &conntrack->status);
    391 }
    392 #endif /* CONFIG_IP_NF_NAT_NEEDED */
    393 
    394 #endif /* __KERNEL__ */
    395 #endif /* _IP_CONNTRACK_H */
    396