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 */ 18union 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 26union 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 */ 38union 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 */ 51union 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) \ 62do { \ 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 73struct ip_conntrack_helper; 74 75struct 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 132struct 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 171static inline struct ip_conntrack * 172tuplehash_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). */ 182extern void 183ip_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). */ 188extern int 189ip_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. */ 193static inline struct ip_conntrack * 194ip_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 */ 201static inline void 202ip_conntrack_put(struct ip_conntrack *ct) 203{ 204 IP_NF_ASSERT(ct); 205 nf_conntrack_put(&ct->ct_general); 206} 207 208extern int invert_tuplepr(struct ip_conntrack_tuple *inverse, 209 const struct ip_conntrack_tuple *orig); 210 211extern 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 */ 218static 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 */ 227static 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 */ 236extern 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. */ 241extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack); 242 243/* Fake conntrack entry for untracked connections */ 244extern struct ip_conntrack ip_conntrack_untracked; 245 246/* Returns new sk_buff, or NULL */ 247struct sk_buff * 248ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user); 249 250/* Iterate over all conntracks: if iter returns true, it's deleted. */ 251extern void 252ip_ct_iterate_cleanup(int (*iter)(struct ip_conntrack *i, void *data), 253 void *data); 254 255extern struct ip_conntrack_helper * 256__ip_conntrack_helper_find_byname(const char *); 257extern struct ip_conntrack_helper * 258ip_conntrack_helper_find_get(const struct ip_conntrack_tuple *tuple); 259extern void ip_conntrack_helper_put(struct ip_conntrack_helper *helper); 260 261extern struct ip_conntrack_protocol * 262__ip_conntrack_proto_find(u_int8_t protocol); 263extern struct ip_conntrack_protocol * 264ip_conntrack_proto_find_get(u_int8_t protocol); 265extern void ip_conntrack_proto_put(struct ip_conntrack_protocol *proto); 266 267extern void ip_ct_remove_expectations(struct ip_conntrack *ct); 268 269extern struct ip_conntrack *ip_conntrack_alloc(struct ip_conntrack_tuple *, 270 struct ip_conntrack_tuple *); 271 272extern void ip_conntrack_free(struct ip_conntrack *ct); 273 274extern void ip_conntrack_hash_insert(struct ip_conntrack *ct); 275 276extern struct ip_conntrack_expect * 277__ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); 278 279extern struct ip_conntrack_expect * 280ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple); 281 282extern struct ip_conntrack_tuple_hash * 283__ip_conntrack_find(const struct ip_conntrack_tuple *tuple, 284 const struct ip_conntrack *ignored_conntrack); 285 286extern void ip_conntrack_flush(void); 287 288/* It's confirmed if it is, or has been in the hash table. */ 289static inline int is_confirmed(struct ip_conntrack *ct) 290{ 291 return test_bit(IPS_CONFIRMED_BIT, &ct->status); 292} 293 294static inline int is_dying(struct ip_conntrack *ct) 295{ 296 return test_bit(IPS_DYING_BIT, &ct->status); 297} 298 299extern unsigned int ip_conntrack_htable_size; 300extern 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 308struct ip_conntrack_ecache { 309 struct ip_conntrack *ct; 310 unsigned int events; 311}; 312DECLARE_PER_CPU(struct ip_conntrack_ecache, ip_conntrack_ecache); 313 314#define CONNTRACK_ECACHE(x) (__get_cpu_var(ip_conntrack_ecache).x) 315 316extern struct atomic_notifier_head ip_conntrack_chain; 317extern struct atomic_notifier_head ip_conntrack_expect_chain; 318 319static inline int ip_conntrack_register_notifier(struct notifier_block *nb) 320{ 321 return atomic_notifier_chain_register(&ip_conntrack_chain, nb); 322} 323 324static inline int ip_conntrack_unregister_notifier(struct notifier_block *nb) 325{ 326 return atomic_notifier_chain_unregister(&ip_conntrack_chain, nb); 327} 328 329static inline int 330ip_conntrack_expect_register_notifier(struct notifier_block *nb) 331{ 332 return atomic_notifier_chain_register(&ip_conntrack_expect_chain, nb); 333} 334 335static inline int 336ip_conntrack_expect_unregister_notifier(struct notifier_block *nb) 337{ 338 return atomic_notifier_chain_unregister(&ip_conntrack_expect_chain, 339 nb); 340} 341 342extern void ip_ct_deliver_cached_events(const struct ip_conntrack *ct); 343extern void __ip_ct_event_cache_init(struct ip_conntrack *ct); 344 345static inline void 346ip_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 360static 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 367static inline void 368ip_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 */ 374static inline void ip_conntrack_event_cache(enum ip_conntrack_events event, 375 const struct sk_buff *skb) {} 376static inline void ip_conntrack_event(enum ip_conntrack_events event, 377 struct ip_conntrack *ct) {} 378static inline void ip_ct_deliver_cached_events(const struct ip_conntrack *ct) {} 379static inline void 380ip_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 385static 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